gh-stack
Compare original and translation side by side
🇺🇸
Original
English🇨🇳
Translation
Chinesegh-stack
gh-stack
gh stackgh stack(main) <- auth <- api <- frontendLeft is the bottom, right is the top. is based on and merges first;
merges last. moves toward the top, away from trunk; moves toward it.
Foundational work belongs at the bottom, code that depends on it above. For how to choose the
layers, read .
authmainfrontendupdownreferences/stack-design.mdgh stackgh stack(main) <- auth <- api <- frontend左侧是底部,右侧是顶部。 基于 ,会最先合并; 最后合并。 朝顶部移动,远离 trunk; 朝 trunk 移动。
authmainfrontendupdown基础性工作应放在底部,依赖它的代码放在上方。有关如何选择各层,请阅读 。
references/stack-design.mdSetup
Setup
Requires Git 2.36+ and an authenticated GitHub CLI.
bash
gh extension install github/gh-stack
git config rerere.enabled true # remember conflict resolutions
git config remote.pushDefault origin # required if the repo has more than one remote需要 Git 2.36+ 和已通过身份验证的 GitHub CLI。
bash
gh extension install github/gh-stack
git config rerere.enabled true # remember conflict resolutions
git config remote.pushDefault origin # required if the repo has more than one remoteNon-interactive use
非交互式使用
gh stackMultiple remotes: never run , , , , or without
unless is configured. and have no
flag and require the config.
pushsubmitsyncrebaselink--remote <name>remote.pushDefaultcheckouttrunk--remote| Always run | Never run bare | Why |
|---|---|---|
| | opens a TUI under a PTY |
| | prompts for a title per new PR |
| | |
| | prompts for branch names |
| | prompts for a name, and fails even when piped |
| | opens a selection menu |
| | |
| — | | TUI-only, no non-interactive path |
- is safe in both modes, but it is formatted for humans. Use
view --shortto parse.--json - when a different local stack already covers those branches cannot be forced. Run
checkout <pr>first (this keeps the stack on GitHub), then retry.gh stack unstack --local - Worktrees: local stacks share one common-directory catalog. Use with navigation or explicit-target
--print-pathto locate a foreign-owned branch without stealing its checkout. Unoccupied targets are checked out here first. Check the exit status before changing directories; parse only successful path-mode stdout, never status messages.checkout
gh stackAgent harness 的行为各不相同,因此始终传入下列 flags,不要依赖该检测机制。
**多个 remote:**除非已配置 ,否则运行 、、、 或 时始终要传入 。 和 没有 flag,并且需要该配置。
remote.pushDefaultpushsubmitsyncrebaselink--remote <name>checkouttrunk--remote| 始终运行 | 不要裸执行 | 原因 |
|---|---|---|
| | 在 PTY 下会打开 TUI |
| | 会提示输入每个新 PR 的标题 |
| | |
| | 会提示输入 branch 名称 |
| | 会提示输入名称,即使在管道模式下也会失败 |
| | 会打开选择菜单 |
| | |
| — | | 仅支持 TUI,没有非交互式路径 |
- 在两种模式下都安全,但它面向人类格式化。需要解析时请使用
view --short。--json - **当另一个本地 stack 已覆盖这些 branch 时,无法强制执行 。**请先运行
checkout <pr>(这会在 GitHub 上保留该 stack),然后重试。gh stack unstack --local - **Worktree:**本地 stack 共享一个 common-directory catalog。将 与导航操作或指定目标的
--print-path一起使用,以定位由其他 worktree 持有的 branch,而不会抢占其 checkout。未被占用的目标会优先在当前 worktree 中 checkout。切换目录前先检查退出状态;只解析路径模式成功时写入 stdout 的内容,绝不要解析状态消息。checkout
Branch placement
Branch 层级安排
- Starting multi-part work: create the stack before writing files. Do not implement every concern on trunk and split it later. Put one dependent concern in each layer, bottom to top.
- Editing an existing stack: check out the layer that owns the change before editing. Never
commit a lower layer's concern on the current top branch. Run ; if ownership is unclear, inspect
gh stack view --json. Then check out the owner, edit, commit, rebase upstack, and return to top.git log --all -- <path>
bash
gh stack down # or: gh stack checkout api
git add ... && git commit -m "Add get-user endpoint"
gh stack rebase --upstack # replay every branch above onto the change
gh stack top # return to where you were
gh stack push- **开始多项工作时:**在编写文件前创建 stack。不要在 trunk 上实现所有工作项,然后再进行拆分。应按从底到顶的顺序,将每个依赖性工作项分别放入一层。
- **编辑现有 stack 时:**先 checkout 负责该变更的 layer,再进行编辑。绝不要在当前顶层 branch 上提交属于底层 layer 的工作。运行 ;如果归属不明确,请检查
gh stack view --json。然后 checkout 所属 branch,编辑、提交、rebase upstack,再返回顶部。git log --all -- <path>
bash
gh stack down # or: gh stack checkout api
git add ... && git commit -m "Add get-user endpoint"
gh stack rebase --upstack # replay every branch above onto the change
gh stack top # return to where you were
gh stack pushCore loop
核心流程
bash
gh stack init auth # create the stack and check out its branch
git add ... && git commit -m "Add auth middleware"
gh stack add api # next layer, branched from the current one
git add ... && git commit -m "Add API routes"
gh stack submit --auto # push every branch and open draft PRs
gh stack view --json # confirmAdd to to create PRs ready for review instead of drafts. Branch names are
verbatim — creates .
--opensubmitgh stack add refactor/foorefactor/foobash
gh stack init auth # create the stack and check out its branch
git add ... && git commit -m "Add auth middleware"
gh stack add api # next layer, branched from the current one
git add ... && git commit -m "Add API routes"
gh stack submit --auto # push every branch and open draft PRs
gh stack view --json # confirm为 添加 ,可以创建已准备好供审查的 PR,而不是 draft PR。Branch 名称会按原样使用—— 会创建 。
submit--opengh stack add refactor/foorefactor/fooStaying in sync
保持同步
bash
gh stack sync # fetch, reconcile with GitHub, rebase, push, refresh PR state
gh stack sync --prune # also delete local branches for merged PRsPruning never happens without when non-interactive. If the local and remote stacks have
diverged, prints both chains, makes no changes, and exits 0 with — see
.
--prunesyncSync abortedreferences/troubleshooting.mdbash
gh stack sync # fetch, reconcile with GitHub, rebase, push, refresh PR state
gh stack sync --prune # also delete local branches for merged PRs在非交互模式下,如果不加 ,绝不会执行 pruning。如果本地和远程 stack 已分叉, 会打印两条 chain,不做任何更改,并以退出码 0 退出并显示 ——参见 。
--prunesyncSync abortedreferences/troubleshooting.mdMerging
合并
Scope the merge with an argument:
bash
gh stack merge 42 --yes # PR #42 plus every unmerged PR below it
gh stack merge 7 --yes # every unmerged PR in stack #7
gh stack merge 42 --yes --squash # or --merge, --rebase, --merge-method <method>Pass a PR number to merge that PR and every unmerged PR below it, or a stack number to merge every
unmerged PR in that stack. The operation is all-or-nothing: if any PR in that set cannot merge,
none do.
Without a method flag the last-used method is reused. If the base branch uses a merge queue, the
stack is queued instead and the queue picks the method, ignoring any flag you passed with a
warning; queued PRs may land in separate groups.
使用参数限定合并范围:
bash
gh stack merge 42 --yes # PR #42 plus every unmerged PR below it
gh stack merge 7 --yes # every unmerged PR in stack #7
gh stack merge 42 --yes --squash # or --merge, --rebase, --merge-method <method>传入 PR 编号时,会合并该 PR 及其下方的每个未合并 PR;传入 stack 编号时,会合并该 stack 中的每个未合并 PR。该操作具有全有或全无语义:如果集合中的任何 PR 无法合并,则所有 PR 都不会合并。
如果不传 method flag,则会沿用上次使用的方法。如果 base branch 使用 merge queue,则 stack 会改为进入队列,由队列决定合并方式,并忽略传入的 flag,同时给出 warning;排队中的 PR 可能以不同 group 合入。
Reading state
读取状态
gh stack view --jsontrunk string
currentBranch string
branches[] name, head, base, isCurrent, isMerged, isQueued, needsRebase
branches[].pr number, url, state ("OPEN" | "MERGED" | "QUEUED"); absent when no PR existsbaseneedsRebasegh stack view --jsontrunk string
currentBranch string
branches[] name, head, base, isCurrent, isMerged, isQueued, needsRebase
branches[].pr number, url, state ("OPEN" | "MERGED" | "QUEUED"); absent when no PR existsbaseneedsRebaseExit codes
退出码
| Code | Meaning | Recovery |
|---|---|---|
| 0 | Success | — |
| 1 | Generic error | Read stderr |
| 2 | Not in a stack | |
| 3 | Rebase conflict | Follow the Exit 3 recovery below |
| 4 | GitHub API failure | Check |
| 5 | Invalid arguments | Fix the invocation; see |
| 6 | Disambiguation required | Branch is in several stacks; check out a non-shared branch |
| 7 | Rebase already in progress | |
| 8 | Stack file locked | Another |
| 9 | Stacked PRs unavailable | Not enabled on the repository; tell the user |
| 10 | Modify recovery required | |
Exit 3 recovery:
- After : resolve the files, run
gh stack rebase, thengit add; usegh stack rebase --continueto restore the stack.gh stack rebase --abort - After : the stack has already been restored. Run
gh stack syncto recreate the conflict, then resolve and continue as above.gh stack rebase
| 代码 | 含义 | 恢复方式 |
|---|---|---|
| 0 | 成功 | — |
| 1 | 通用错误 | 读取 stderr |
| 2 | 不在任何 stack 中 | |
| 3 | Rebase 冲突 | 按照下方“退出码 3 的恢复方式”操作 |
| 4 | GitHub API 失败 | 检查 |
| 5 | 参数无效 | 修正调用方式;参见 |
| 6 | 需要消除歧义 | 该 branch 同时位于多个 stack 中;请 checkout 一个非共享 branch |
| 7 | Rebase 已在进行中 | |
| 8 | Stack 文件已锁定 | 另一个 |
| 9 | 堆叠式 PR 不可用 | 仓库未启用;请告知用户 |
| 10 | 需要恢复 modify 操作 | |
退出码 3 的恢复方式:
- 执行 后:解决文件冲突,运行
gh stack rebase,然后执行git add;使用gh stack rebase --continue可恢复 stack。gh stack rebase --abort - 执行 后:stack 已恢复。运行
gh stack sync重新触发冲突,然后按照上述方式解决并继续。gh stack rebase
Constraints
限制
- Stacks are strictly linear: one parent, at most one child. Use separate stacks for parallel work.
- and
rebaseautomatically update affected clean worktrees; they never auto-stash or create/remove worktrees. Mutations serialize across the clone, and paused operations require recovery in their recorded owners.sync - supports distributed stack branches, but its editor remains TUI-only. Actions run in affected clean owners; unoccupied branches use the origin. Drop/fold source branches and worktrees are preserved. Recovery flags may run from any worktree and use recorded native operation owners; never resolve/stage in the caller's tree unless the diagnostic names it.
modify - There is no non-interactive reorder or removal. Errors may suggest , but it is TUI-only — restructure with
gh stack modifythenunstackinstead.init - PR titles and bodies are auto-generated. Use afterwards to change them.
gh pr edit
- Stack 严格保持线性结构:一个 parent,最多一个 child。并行工作应使用不同的 stack。
- 和
rebase会自动更新受影响的干净 worktree;它们不会自动 stash,也不会创建或移除 worktree。修改操作会在整个 clone 内串行执行;暂停的操作必须在记录其 owner 的位置恢复。sync - 支持分布式 stack branch,但其编辑器仍仅支持 TUI。相关操作会在受影响的干净 owner 中执行;未被占用的 branch 使用 origin。Drop/fold 的 source branch 和 worktree 会保留。Recovery flag 可以从任意 worktree 运行,并使用已记录的原生命令 owner;除非诊断信息明确指出,否则绝不要在调用方的 tree 中解决冲突或执行 staging。
modify - 不存在非交互式的 reorder 或 removal。错误可能建议 ,但它仅支持 TUI——应改用
gh stack modify后再unstack来重组。init - PR 标题和正文会自动生成。之后可使用 修改。
gh pr edit
More detail
更多信息
gh stack <command> --helpgh stack help <command>Open the reference whose trigger matches the task; no need to preload all three.
- — read before creating a stack, when deciding how many layers to use, what belongs in each one, or whether work belongs in a new stack.
references/stack-design.md - — read when a command fails unexpectedly or you need its preconditions, side effects, atomicity, or ordering guarantees.
references/commands.md - — read on a rebase conflict, after a squash-merge, on local and remote divergence, when restructuring a stack, or when driving stacks from another tool.
references/troubleshooting.md
gh stack <command> --helpgh stack help <command>仅打开与当前任务触发条件匹配的 reference;无需预加载全部三个。
- ——在创建 stack 前、决定使用多少 layer、每一层应包含什么,或工作是否应放入新 stack 时阅读。
references/stack-design.md - ——在命令意外失败,或需要了解其 precondition、side effect、atomicity 或 ordering guarantee 时阅读。
references/commands.md - ——在遇到 rebase 冲突、squash-merge 后、local 和 remote divergence、重构 stack,或从另一工具驱动 stack 时阅读。
references/troubleshooting.md