graphite

Compare original and translation side by side

🇺🇸

Original

English
🇨🇳

Translation

Chinese

Graphite Skill

Graphite使用技巧

Work with Graphite (
gt
) for creating, navigating, and managing stacked pull requests.
使用Graphite (
gt
) 创建、导航和管理堆叠拉取请求。

Quick Reference

快速参考

I want to...Command
Create a new branch/PR
gt create branch-name -m "message"
Amend current branch
gt modify -m "message"
Navigate up the stack
gt up
Navigate down the stack
gt down
Jump to top of stack
gt top
Jump to bottom of stack
gt bottom
View stack structure
gt ls
Submit stack for review
gt submit --no-interactive
Rebase stack on trunk
gt restack
Change branch parent
gt track --parent <branch>
Rename current branch
gt rename <new-name>
Move branch in stack
gt move

我想要...命令
创建新分支/PR
gt 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

What Makes a Good PR?

什么样的PR是合格的?

In roughly descending order of importance:
  • Atomic/hermetic - independent of other changes; will pass CI and be safe to deploy on its own
  • Narrow semantic scope - changes only to module X, or the same change across modules X, Y, Z
  • Small diff - (heuristic) small total diff line count
Do NOT worry about creating TOO MANY pull requests. It is always preferable to create more pull requests than fewer.
NO CHANGE IS TOO SMALL: tiny PRs allow for the medium/larger-sized PRs to have more clarity.
Always argue in favor of creating more PRs, as long as they independently pass build.

按重要性大致降序排列:
  • 原子性/密封性:独立于其他改动,可单独通过CI且单独部署也安全
  • 语义范围窄:仅修改模块X,或在X、Y、Z模块中做同类型改动
  • 差异小:(经验法则)总差异行数少
不用担心创建太多PR,PR数量多永远比数量少更可取。
再小的改动也值得提PR: 小型PR能让中大型PR的内容更清晰。
只要PR能独立通过构建,永远鼓励创建更多PR。

Branch Naming Conventions

分支命名规范

When naming PRs in a stack, follow this syntax:
terse-stack-feature-name/terse-description-of-change
For example, a 4 PR stack:
auth-bugfix/reorder-args
auth-bugfix/improve-logging
auth-bugfix/improve-documentation
auth-bugfix/handle-401-status-codes

给堆栈中的PR命名时,遵循以下语法:
精简堆栈功能名/改动的精简描述
例如一个包含4个PR的堆栈:
auth-bugfix/reorder-args
auth-bugfix/improve-logging
auth-bugfix/improve-documentation
auth-bugfix/handle-401-status-codes

Creating a Stack

创建堆栈

Basic Workflow

基础工作流

  1. Make changes to files
  2. Stage changes:
    git add <files>
  3. Create branch:
    gt create branch-name -m "commit message"
  4. Repeat for each PR in the stack
  5. Submit:
    gt submit --no-interactive
  1. 修改文件
  2. 暂存改动:
    git add <files>
  3. 创建分支:
    gt create branch-name -m "commit message"
  4. 为堆栈中的每个PR重复上述步骤
  5. 提交:
    gt submit --no-interactive

Handle Untracked Branches (common with worktrees)

处理未跟踪分支(worktree场景常见)

Before creating branches, check if the current branch is tracked:
bash
gt branch info
If you see "ERROR: Cannot perform this operation on untracked branch":
Option A (Recommended): Track temporarily, then re-parent
  1. Track current branch:
    gt track -p main
  2. Create your stack normally with
    gt create
  3. After creating ALL branches, re-parent your first new branch onto main:
    bash
    gt checkout <first-branch-of-your-stack>
    gt track -p main
    gt restack
Option B: Stash changes and start from main
  1. git stash
  2. git checkout main && git pull
  3. Create new branch and unstash:
    git checkout -b temp-working && git stash pop
  4. Proceed with
    gt track -p main
    and
    gt create

创建分支前,先检查当前分支是否被跟踪:
bash
gt branch info
如果看到"ERROR: Cannot perform this operation on untracked branch":
选项A(推荐):临时跟踪,再重新设置父级
  1. 跟踪当前分支:
    gt track -p main
  2. gt create
    正常创建你的堆栈
  3. 创建完所有分支后,将第一个新分支的父级重新设置为main:
    bash
    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
    继续操作

Navigating a Stack

导航堆栈

bash
undefined
bash
undefined

Move up one branch (toward top of stack)

向上移动一个分支(朝向堆栈顶部)

gt up
gt up

Move down one branch (toward trunk)

向下移动一个分支(朝向主干)

gt down
gt down

Jump to top of stack

跳转到堆栈顶部

gt top
gt top

Jump to bottom of stack (first branch above trunk)

跳转到堆栈底部(主干之上的第一个分支)

gt bottom
gt bottom

View the full stack structure

查看完整堆栈结构

gt ls

---
gt ls

---

Modifying a Stack

修改堆栈

Amend Current Branch

修订当前分支

bash
git add <files>
gt modify -m "updated commit message"
bash
git add <files>
gt modify -m "updated commit message"

Reorder Branches

重排分支顺序

Use
gt move
to reorder branches in the stack. This is simpler than trying to use
gt create --insert
.
使用
gt move
重排堆栈中的分支,比使用
gt create --insert
更简单。

Re-parent a Stack

重新设置堆栈父级

If you created a stack on top of a feature branch but want it based on main:
bash
undefined
如果你是基于一个功能分支创建的堆栈,但想要将其基于main分支:
bash
undefined

Go to first branch of your stack

切换到堆栈的第一个分支

gt checkout <first-branch>
gt checkout <first-branch>

Change its parent to main

将其父级改为main

gt track --parent main
gt track --parent main

Rebase the entire stack

变基整个堆栈

gt restack
undefined
gt restack
undefined

Rename a Branch

重命名分支

bash
gt rename new-branch-name

bash
gt rename new-branch-name

Resetting Commits to Unstaged Changes

将提交重置为未暂存改动

If changes are already committed but you want to re-stack them differently:
bash
undefined
如果改动已经提交,但你想要重新调整堆栈结构:
bash
undefined

Reset the last commit, keeping changes unstaged

重置最后一次提交,保留改动为未暂存状态

git reset HEAD^
git reset HEAD^

Reset multiple commits (e.g., last 2 commits)

重置多次提交(例如最近2次提交)

git reset HEAD~2
git reset HEAD~2

View the diff to understand what you're working with

查看diff了解当前改动内容

git diff HEAD

---
git diff HEAD

---

Before Submitting

提交前检查

Verify Stack is Rooted on Main

验证堆栈根基于main分支

Before running
gt submit
, verify the first PR is parented on
main
:
bash
gt ls
If the first branch has a parent other than
main
:
bash
gt checkout <first-branch>
gt track -p main
gt restack
运行
gt submit
前,确认第一个PR的父级是
main
bash
gt ls
如果第一个分支的父级不是
main
bash
gt checkout <first-branch>
gt track -p main
gt restack

Run Validation

运行校验

After creating each PR, run appropriate linting, building, and testing:
  1. Refer to the project's CLAUDE.md for specific commands
  2. If validation fails, fix the issue, stage changes, and use
    gt modify

创建每个PR后,运行对应的 lint、构建和测试流程:
  1. 参考项目的CLAUDE.md获取具体命令
  2. 如果校验失败,修复问题,暂存改动,使用
    gt modify
    修订

Submitting and Updating PRs

提交和更新PR

Submit the Stack

提交堆栈

bash
gt submit --no-interactive
bash
gt submit --no-interactive

Update PR Descriptions

更新PR描述

After submitting, use
gh pr edit
to set proper titles and descriptions.
IMPORTANT: Never use Bash heredocs for PR descriptions - shell escaping breaks markdown tables, code blocks, etc. Instead:
  1. Use the
    Write
    tool to create
    /tmp/pr-body.md
    with the full markdown content
  2. Use
    gh pr edit
    with
    --body-file
    :
bash
gh pr edit <PR_NUMBER> --title "stack-name: description" --body-file /tmp/pr-body.md
PR descriptions must include:
  • Stack Context: What is the bigger goal of this stack?
  • What? (optional for small changes): Super terse, focus on what not why
  • Why?: What prompted the change? Why this solution? How does it fit into the stack?
Example (for a PR in a 3-PR stack adding a warning feature):
markdown
undefined
提交后,使用
gh pr edit
设置合适的标题和描述。
重要提示: 不要使用Bash heredoc编写PR描述——shell转义会破坏markdown表格、代码块等。推荐做法:
  1. 使用Write工具创建包含完整markdown内容的
    /tmp/pr-body.md
    文件
  2. 使用
    gh pr edit
    --body-file
    参数加载文件:
bash
gh pr edit <PR_NUMBER> --title "stack-name: description" --body-file /tmp/pr-body.md
PR描述必须包含:
  • 堆栈上下文:这个堆栈的整体目标是什么?
  • 改动内容(小改动可选):非常精简,重点是改了什么而不是为什么改
  • 改动原因:为什么要做这个改动?为什么选择这个方案?它在堆栈中起到什么作用?
示例(一个3PR堆栈中添加警告功能的某一个PR描述):
markdown
undefined

Stack Context

堆栈上下文

This stack adds a warning on the merge button when users are bypassing GitHub rulesets.
这个堆栈的功能是当用户绕过GitHub规则集时,在合并按钮上添加警告提示。

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.

---
有权限绕过规则集的用户(组织管理员或团队成员)目前看不到任何提示,不知道自己正在绕过分支保护。这个PR将绕过权限数据从服务端传递到前端,为后续PR(第2个PR)展示警告提供支持。

---

Troubleshooting

问题排查

ProblemSolution
"Cannot perform this operation on untracked branch"Run
gt track -p main
first
Stack parented on wrong branchUse
gt track -p main
then
gt restack
Need to reorder PRsUse
gt move
Conflicts during restackResolve conflicts, then
git rebase --continue
Want to split a PRReset commits (
git reset HEAD^
), re-stage selectively, create new branches
Need to delete a branch (non-interactive)
gt delete <branch> -f -q
gt restack
hitting unrelated conflicts
Use targeted
git rebase <target>
instead (see below)
Rebase interrupted mid-conflictCheck if files are resolved but unstaged, then
git add
+
git rebase --continue

问题解决方案
"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>
(见下文)
变基中途因冲突中断检查文件是否已经解决冲突只是未暂存,然后
git add
+
git rebase --continue

Advanced: Surgical Rebasing in Complex Stacks

进阶:复杂堆栈中的精准变基

In deeply nested stacks with many sibling branches,
gt restack
can be problematic:
  • It restacks ALL branches that need it, not just your stack
  • Can hit conflicts in completely unrelated branches
  • Is all-or-nothing - hard to be surgical
在包含很多同级分支的深度嵌套堆栈中,
gt restack
可能会有问题:
  • 它会变基所有需要更新的分支,而不只是你的堆栈
  • 可能在完全无关的分支中遇到冲突
  • 是全量操作,很难做到精准调整

When to Use
git rebase
Instead of
gt restack

什么时候应该用
git rebase
代替
gt restack

Use direct
git rebase
when:
  • You only want to update specific branches in your stack
  • gt restack
    is hitting conflicts in unrelated branches
  • You need to skip obsolete commits during the rebase
符合以下场景时使用直接
git rebase
  • 你只想更新堆栈中的特定分支
  • gt restack
    在无关分支中遇到冲突
  • 你需要在变基过程中跳过过时的提交

Targeted Rebase Workflow

定向变基工作流

bash
undefined
bash
undefined

1. Checkout the branch you want to rebase

1. 切换到你想要变基的分支

git checkout my-feature-branch
git checkout my-feature-branch

2. Rebase onto the target (e.g., updated parent branch)

2. 变基到目标分支(例如更新后的父分支)

git rebase target-branch
git rebase target-branch

3. If you hit conflicts:

3. 如果遇到冲突:

- Resolve the conflict in the file

- 在文件中解决冲突

- Stage it: git add <file>

- 暂存文件:git add <file>

- Continue: git rebase --continue

- 继续变基:git rebase --continue

4. If a commit is obsolete and should be skipped:

4. 如果某个提交已经过时应该跳过:

git rebase --skip
git rebase --skip

5. After rebase, use gt modify to sync graphite's tracking

5. 变基完成后,使用gt modify同步graphite的跟踪信息

gt modify --no-edit
undefined
gt modify --no-edit
undefined

Recovering from Interrupted Rebase (Context Reset)

从中断的变基中恢复(上下文重置场景)

If a rebase was interrupted (e.g., Claude session ran out of context):
  1. Check status:
    bash
    git status
    # Look for "interactive rebase in progress" and "Unmerged paths"
  2. Read the "unmerged" files - they may already be resolved (no conflict markers)
  3. If already resolved, just stage and continue:
    bash
    git add <resolved-files>
    git rebase --continue
  4. If still has conflict markers, resolve them first, then stage and continue
如果变基被中断(例如Claude会话上下文耗尽):
  1. 检查状态:
    bash
    git status
    # 查找"interactive rebase in progress"和"Unmerged paths"提示
  2. 查看「未合并」文件——它们可能已经解决了冲突(没有冲突标记)
  3. 如果已经解决冲突,直接暂存并继续:
    bash
    git add <resolved-files>
    git rebase --continue
  4. 如果还有冲突标记,先解决冲突,再暂存并继续

Deleting Branches from a Stack

从堆栈中删除分支

bash
undefined
bash
undefined

Delete a branch (non-interactive, even if not merged)

删除分支(非交互模式,即使未合并也可删除)

gt delete branch-to-delete -f -q
gt delete branch-to-delete -f -q

Also delete all children (upstack)

同时删除所有子分支(上游堆栈)

gt delete branch-to-delete -f -q --upstack
gt delete branch-to-delete -f -q --upstack

Also delete all ancestors (downstack)

同时删除所有祖先分支(下游堆栈)

gt delete branch-to-delete -f -q --downstack

**Flags:**
- `-f` / `--force`: Delete even if not merged or closed
- `-q` / `--quiet`: Implies `--no-interactive`, minimizes output

**After deleting intermediate branches**, children are automatically restacked onto the parent. If you need to manually update tracking:
```bash
gt checkout child-branch
gt track --parent new-parent-branch
gt delete branch-to-delete -f -q --downstack

**参数说明:**
- `-f` / `--force`:即使分支未合并或未关闭也强制删除
- `-q` / `--quiet`:隐含`--no-interactive`,最小化输出

**删除中间分支后**,子分支会自动重新变基到父分支。如果需要手动更新跟踪信息:
```bash
gt checkout child-branch
gt track --parent new-parent-branch