mcpField
G
graphite

graphite

github.com/withgraphite开发710.0k 次安装36 周前更新
代码仓库

关于 graphite

Graphite Skill 提供使用 Graphite(`gt`)创建、导航和管理堆叠式 Pull Request 的命令指引,面向维护分支堆栈的开发者,涵盖提交、变基和故障恢复流程。

主要功能

  1. 01创建并修改堆叠分支
  2. 02导航和查看分支堆栈
  3. 03提交堆栈以供审查
  4. 04调整分支顺序和父级
  5. 05重新堆叠分支并处理冲突
  6. 06恢复中断的变基

适用场景

  1. 01构建一组范围明确的 Pull Request
  2. 02在堆栈分支间切换
  3. 03将堆栈变基到 main
  4. 04处理更新堆栈时的问题

安装

复制下面的命令,在终端中运行。

$npx skills add https://github.com/withgraphite/agent-skills --skill graphite

安装后在 Claude Code 中输入/graphite确认已加载。

详细介绍

Graphite 技能

使用 Graphite(gt)创建、浏览和管理堆叠式拉取请求。

快速参考

我想要……命令
创建新分支/PRgt create branch-name -m "message"
修改当前分支gt modify -m "message"
向上浏览堆栈gt up
向下浏览堆栈gt down
跳到堆栈顶部gt top
跳到堆栈底部gt bottom
查看堆栈结构gt ls
提交堆栈以供审查gt submit --no-interactive
将堆栈变基到主干分支gt restack
更改分支父级gt track --parent <branch>
重命名当前分支gt rename <new-name>
移动堆栈中的分支gt move

什么样的 PR 才算好?

大致按重要性降序排列:

  • 原子化/自包含 - 不依赖其他更改;可通过 CI,并且单独部署也安全
  • 语义范围窄 - 只更改模块 X,或在模块 X、Y、Z 中进行相同的更改
  • 差异小 - (经验法则)总差异行数较少

不要担心创建太多拉取请求。 创建更多拉取请求总是优于创建更少拉取请求。

再小的更改也值得提交: 微小的 PR 有助于让中型/大型 PR 更清晰。

只要每个 PR 都能独立通过构建,就应始终倾向于创建更多 PR。


分支命名约定

为堆栈中的 PR 命名时,请遵循以下格式:

terse-stack-feature-name/terse-description-of-change

例如,一个包含 4 个 PR 的堆栈:

auth-bugfix/reorder-args
auth-bugfix/improve-logging
auth-bugfix/improve-documentation
auth-bugfix/handle-401-status-codes

创建堆栈

基本工作流
  1. 修改文件
  2. 暂存更改:git add <files>
  3. 创建分支:gt create branch-name -m "commit message"
  4. 为堆栈中的每个 PR 重复上述步骤
  5. 提交:gt submit --no-interactive
处理未跟踪的分支(worktree 中很常见)

创建分支前,检查当前分支是否已被跟踪:

gt branch info

如果看到“ERROR: Cannot perform this operation on untracked branch”:

选项 A(推荐):先临时跟踪,再重新设置父级

  1. 跟踪当前分支:gt track -p main
  2. 使用 gt create 正常创建堆栈
  3. 创建完所有分支后,将第一个新分支的父级重新设为 main:
    gt checkout <first-branch-of-your-stack>
    gt track -p main
    gt restack
    

选项 B:暂存更改并从 main 开始

  1. git stash
  2. git checkout main && git pull
  3. 创建新分支并恢复暂存的更改:git checkout -b temp-working && git stash pop
  4. 继续执行 gt track -p main 和 gt create

浏览堆栈

# Move up one branch (toward top of stack)
gt up

# Move down one branch (toward trunk)
gt down

# Jump to top of stack
gt top

# Jump to bottom of stack (first branch above trunk)
gt bottom

# View the full stack structure
gt ls

修改堆栈

修改当前分支
git add <files>
gt modify -m "updated commit message"
重新排序分支

使用 gt move 重新排列堆栈中的分支。这比尝试使用 gt create --insert 更简单。

重新设置堆栈的父级

如果你在某个功能分支上创建了堆栈,但希望以 main 为基础:

# Go to first branch of your stack
gt checkout <first-branch>

# Change its parent to main
gt track --parent main

# Rebase the entire stack
gt restack
重命名分支
gt rename new-branch-name

将提交重置为未暂存的更改

如果更改已经提交,但你想以不同方式重新堆叠:

# Reset the last commit, keeping changes unstaged
git reset HEAD^

# Reset multiple commits (e.g., last 2 commits)
git reset HEAD~2

# View the diff to understand what you're working with
git diff HEAD

提交前

确认堆栈以 main 为根

运行 gt submit 前,确认第一个 PR 的父级是 main:

gt ls

如果第一个分支的父级不是 main:

gt checkout <first-branch>
gt track -p main
gt restack
运行验证

创建每个 PR 后,运行适当的代码检查、构建和测试:

  1. 参考项目的 CLAUDE.md,了解具体命令
  2. 如果验证失败,修复问题、暂存更改,然后使用 gt modify

提交和更新 PR

提交堆栈
gt submit --no-interactive
更新 PR 描述

提交后,使用 gh pr edit 设置合适的标题和描述。

**重要:**切勿使用 Bash heredoc 编写 PR 描述——shell 转义会破坏 Markdown 表格、代码块等内容。请改用以下方式:

  1. 使用 Write 工具创建 /tmp/pr-body.md,写入完整的 Markdown 内容
  2. 使用 gh pr edit 和 --body-file:
gh pr edit <PR_NUMBER> --title "stack-name: description" --body-file /tmp/pr-body.md

PR 描述必须包含:

  • Stack Context:此堆栈的更大目标是什么?
  • What?(小改动可选):尽量简洁,重点说明改了什么,而不是为什么改
  • Why?:是什么促成了这次改动?为什么选择此方案?它如何融入堆栈?

示例(在一个由 3 个 PR 组成、用于添加警告功能的堆栈中提交 PR):

## Stack Context

This stack adds a warning on the merge button when users are bypassing GitHub rulesets.

## Why?

Users who can bypass rulesets (via org admin or team membership) currently see no indication
they're circumventing branch protection. This PR threads the bypass data from the server to
enable the frontend warning (PR 2) to display it.

故障排除

问题解决方案
"Cannot perform this operation on untracked branch"先运行 gt track -p main
堆栈的父分支不正确使用 gt track -p main,然后运行 gt restack
需要调整 PR 顺序使用 gt move
restack 期间发生冲突解决冲突,然后运行 git rebase --continue
想要拆分 PR重置提交(git reset HEAD^),选择性地重新暂存,然后创建新分支
需要删除分支(非交互模式)gt delete <branch> -f -q
gt restack 遇到无关冲突改用指定目标的 git rebase <target>(见下文)
rebase 在冲突处理中断检查文件是否已解决但尚未暂存,然后运行 git add 和 git rebase --continue

进阶:在复杂堆栈中精准 rebase

在分支众多、嵌套层级较深的堆栈中,gt restack 可能会带来问题:

  • 它会重排所有需要重排的分支,而不只是你的堆栈
  • 可能会遇到完全无关分支中的冲突
  • 它会一次性全部执行,很难精准控制
何时使用 git rebase 而不是 gt restack

在以下情况下,使用直接的 git rebase:

  • 你只想更新堆栈中的特定分支
  • gt restack 在无关分支中遇到冲突
  • 你需要在 rebase 期间跳过过时的提交
指定目标的 rebase 工作流
# 1. Checkout the branch you want to rebase
git checkout my-feature-branch

# 2. Rebase onto the target (e.g., updated parent branch)
git rebase target-branch

# 3. If you hit conflicts:
#    - Resolve the conflict in the file
#    - Stage it: git add <file>
#    - Continue: git rebase --continue

# 4. If a commit is obsolete and should be skipped:
git rebase --skip

# 5. After rebase, use gt modify to sync graphite's tracking
gt modify --no-edit
从中断的 rebase 中恢复(上下文重置)

如果 rebase 中断(例如,Claude 会话耗尽上下文):

  1. 检查状态:

    git status
    # Look for "interactive rebase in progress" and "Unmerged paths"
    
  2. 查看“未合并”的文件——它们可能已经解决(不含冲突标记)

  3. 如果冲突已解决,只需暂存并继续:

    git add <resolved-files>
    git rebase --continue
    
  4. 如果仍有冲突标记,先解决冲突,然后暂存并继续

从堆栈中删除分支
# Delete a branch (non-interactive, even if not merged)
gt delete branch-to-delete -f -q

# Also delete all children (upstack)
gt delete branch-to-delete -f -q --upstack

# Also delete all ancestors (downstack)
gt delete branch-to-delete -f -q --downstack

标志:

  • -f / --force:即使分支尚未合并或已关闭,也强制删除
  • -q / --quiet:隐含 --no-interactive,减少输出

删除中间分支后,其子分支会自动重排到父分支之上。如果需要手动更新跟踪关系:

gt checkout child-branch
gt track --parent new-parent-branch

评论

支持 Markdown