gh-stack

Compare original and translation side by side

🇺🇸

Original

English
🇨🇳

Translation

Chinese

gh-stack

gh-stack

gh stack
is a GitHub CLI extension for stacked branches and pull requests. A stack is an ordered chain of branches rooted on a trunk, where each branch has one PR based on the branch below it, so a reviewer sees only that layer's diff.
gh stack
prints a stack trunk-first, left to right:
(main) <- auth <- api <- frontend
Left is the bottom, right is the top.
auth
is based on
main
and merges first;
frontend
merges last.
up
moves toward the top, away from trunk;
down
moves toward it. Foundational work belongs at the bottom, code that depends on it above. For how to choose the layers, read
references/stack-design.md
.
gh stack
是一款用于堆叠分支和PR(Pull Request)的GitHub CLI扩展。堆叠是指以主干为根的有序分支链,每个分支都基于其下方的分支创建一个PR,因此评审者只能看到该层级的diff。
gh stack
以主干优先的顺序打印堆叠,从左到右:
(main) <- auth <- api <- frontend
左侧是底部,右侧是顶部
auth
基于
main
创建,会最先合并;
frontend
最后合并。
up
指令朝向顶部移动,远离主干;
down
指令朝向主干移动。基础工作应放在底部,依赖它的代码放在上方。关于如何选择层级,请阅读
references/stack-design.md

Setup

安装配置

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
bash
gh extension install github/gh-stack
git config rerere.enabled true         # 记住冲突解决方案
git config remote.pushDefault origin   # 若仓库有多个远程仓库则需配置此项

Non-interactive use

非交互式使用

gh stack
branches on whether stdout is a TTY. Piped, most commands error cleanly or print static text; under a PTY the same commands open a prompt or a full-screen TUI and block forever. Agent harnesses differ, so always pass the flags below instead of relying on that detection.
Multiple remotes: never run
push
,
submit
,
sync
,
rebase
, or
link
without
--remote <name>
unless
remote.pushDefault
is configured.
checkout
and
trunk
have no
--remote
flag and require the config.
Always runNever run bareWhy
gh stack view --json
gh stack view
opens a TUI under a PTY
gh stack submit --auto
gh stack submit
prompts for a title per new PR
gh stack merge <target> --yes
gh pr merge
gh pr merge
cannot merge a stack
gh stack init <branch>...
gh stack init
prompts for branch names
gh stack add <branch>
gh stack add
prompts for a name, and fails even when piped
gh stack checkout <target>
gh stack checkout
opens a selection menu
gh stack up
/
down
/
top
/
bottom
gh stack switch
switch
is menu-only
(none)
gh stack modify
TUI-only, no non-interactive path
  • view --short
    is safe in both modes, but it is formatted for humans. Use
    --json
    to parse.
  • checkout <pr>
    when a different local stack already covers those branches
    cannot be forced. Run
    gh stack unstack --local
    first (this keeps the stack on GitHub), then retry.
gh stack
的行为取决于stdout是否为TTY。当通过管道执行时,大多数命令会清晰报错或打印静态文本;在PTY环境下,相同命令会打开提示符或全屏TUI并一直阻塞。Agent的运行环境各不相同,因此请始终传递以下标志,不要依赖这种自动检测。
多远程仓库场景: 除非配置了
remote.pushDefault
,否则执行
push
submit
sync
rebase
link
时必须加上
--remote <name>
参数。
checkout
trunk
没有
--remote
标志,需要提前配置好上述参数。
始终运行切勿裸运行原因
gh stack view --json
gh stack view
在PTY环境下会打开TUI
gh stack submit --auto
gh stack submit
会为每个新PR提示输入标题
gh stack merge <target> --yes
gh pr merge
gh pr merge
无法合并堆叠
gh stack init <branch>...
gh stack init
会提示输入分支名称
gh stack add <branch>
gh stack add
会提示输入名称,即使通过管道执行也会失败
gh stack checkout <target>
gh stack checkout
会打开选择菜单
gh stack up
/
down
/
top
/
bottom
gh stack switch
switch
仅支持菜单交互
gh stack modify
仅支持TUI交互,无非交互执行路径
  • view --short
    在两种模式下都可安全使用,但它是为人类阅读设计的格式。如需解析,请使用
    --json
    参数。
  • 当本地已有其他堆叠覆盖目标分支时,
    checkout <pr>
    无法强制执行
    。请先运行
    gh stack unstack --local
    (此操作会保留GitHub上的堆叠),然后重试。

Branch placement

分支放置原则

  • 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
    gh stack view --json
    ; if ownership is unclear, inspect
    git log --all -- <path>
    . Then check out the owner, edit, commit, rebase upstack, and return to top.
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
  • 启动多部分工作: 在编写代码前创建堆叠。不要在主干上实现所有需求后再拆分。将每个依赖项放在单独的层级中,从下到上排列。
  • 编辑现有堆叠: 在编辑前检出负责该变更的层级。绝不要在当前顶部分支提交属于下层的变更。运行
    gh stack view --json
    ;若归属关系不清晰,请检查
    git log --all -- <path>
    。然后检出归属分支,进行编辑、提交、向上rebase堆叠,最后返回顶部分支。
bash
gh stack down                   # 或:gh stack checkout api
git add ... && git commit -m "Add get-user endpoint"
gh stack rebase --upstack       # 将上方所有分支重放至变更之上
gh stack top                    # 返回之前所在的分支
gh stack push

Core 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            # confirm
Add
--open
to
submit
to create PRs ready for review instead of drafts. Branch names are verbatim:
gh stack add refactor/foo
creates
refactor/foo
.
bash
gh stack init auth              # 创建堆叠并检出其分支
git add ... && git commit -m "Add auth middleware"
gh stack add api                # 创建下一层级,基于当前分支
git add ... && git commit -m "Add API routes"
gh stack submit --auto          # 推送所有分支并打开草稿PR
gh stack view --json            # 确认状态
submit
中添加
--open
参数可创建可供评审的PR,而非草稿。分支名称会原样使用:
gh stack add refactor/foo
会创建
refactor/foo
分支。

Staying 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 PRs
Pruning never happens without
--prune
when non-interactive. If the local and remote stacks have diverged,
sync
prints both chains, makes no changes, and exits 0 with
Sync aborted
; see
references/troubleshooting.md
.
bash
gh stack sync                   # 拉取代码、与GitHub协调、rebase、推送、刷新PR状态
gh stack sync --prune           # 同时删除已合并PR对应的本地分支
非交互模式下,不加
--prune
参数不会执行清理操作。若本地与远程堆叠出现分歧,
sync
会打印两条分支链,不做任何修改,然后以状态码0退出并提示
Sync aborted
;请查看
references/troubleshooting.md

Merging

合并操作

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及其下方所有未合并的PR
gh stack merge 7 --yes           # 合并堆叠#7中所有未合并的PR
gh stack merge 42 --yes --squash # 或使用 --merge、--rebase、--merge-method <method>
传入PR编号会合并该PR及其下方所有未合并的PR;传入堆叠编号会合并该堆叠中所有未合并的PR。此操作是原子性的:若集合中任意PR无法合并,则所有PR都不会合并。
若未指定合并方法,会使用上次使用的方法。若基础分支使用合并队列,则堆叠会被加入队列,由队列选择合并方法,此时会忽略你传入的方法参数并给出警告;进入队列的PR可能会被分成多个组合并。

Reading state

状态读取

gh stack view --json
writes JSON to stdout. Status messages go to stderr. Do not parse them; branch on exit codes instead.
trunk           string
currentBranch   string
branches[]      name, head, base, isCurrent, isMerged, isQueued, needsRebase
branches[].pr   number, url, state ("OPEN" | "MERGED" | "QUEUED"); absent when no PR exists
base
is the saved SHA of the parent branch that this branch was last known to contain. It may be older than the parent's current tip.
needsRebase
is true when the current parent tip is no longer an ancestor of the branch.
gh stack view --json
会将JSON写入stdout,状态信息会输出到stderr。请勿解析stderr内容;请根据退出码判断执行结果。
trunk           string
currentBranch   string
branches[]      name, head, base, isCurrent, isMerged, isQueued, needsRebase
branches[].pr   number, url, state ("OPEN" | "MERGED" | "QUEUED"); 无PR时不会返回此字段
base
是该分支最后已知包含的父分支SHA值,可能早于父分支当前的最新提交。当父分支当前最新提交不再是该分支的祖先时,
needsRebase
会为true。

Exit codes

退出码

CodeMeaningRecovery
0Success(none)
1Generic errorRead stderr
2Not in a stack
gh stack init
, or
gh stack checkout <target>
3Rebase conflictFollow the Exit 3 recovery below
4GitHub API failureCheck
gh auth status
, retry
5Invalid argumentsFix the invocation; see
<command> --help
6Disambiguation requiredBranch is in several stacks; check out a non-shared branch
7Rebase already in progress
gh stack rebase --continue
or
--abort
8Stack file lockedAnother
gh stack
process is writing; retry after ~5s
9Stacked PRs unavailableNot enabled on the repository; tell the user
10Modify recovery required
gh stack modify --abort
Exit 3 recovery:
  • After
    gh stack rebase
    : resolve the files, run
    git add
    , then
    gh stack rebase --continue
    ; use
    gh stack rebase --abort
    to restore the stack.
  • After
    gh stack sync
    : the stack has already been restored. Run
    gh stack rebase
    to recreate the conflict, then resolve and continue as above.
代码含义恢复方法
0执行成功
1通用错误查看stderr内容
2未处于堆叠中执行
gh stack init
,或
gh stack checkout <target>
3Rebase冲突按照下方退出码3的恢复步骤操作
4GitHub API调用失败检查
gh auth status
,重试
5参数无效修改命令参数;查看
<command> --help
6需要消除歧义分支存在于多个堆叠中;检出一个非共享分支
7Rebase已在进行中执行
gh stack rebase --continue
--abort
8堆叠文件被锁定另一个
gh stack
进程正在写入;等待约5秒后重试
9堆叠PR不可用仓库未启用该功能;告知用户
10需要恢复Modify操作执行
gh stack modify --abort
退出码3的恢复步骤:
  • 执行
    gh stack rebase
    后:解决文件冲突,运行
    git add
    ,然后执行
    gh stack rebase --continue
    ;若需恢复堆叠,执行
    gh stack rebase --abort
  • 执行
    gh stack sync
    后:堆叠已恢复。执行
    gh stack rebase
    重新触发冲突,然后按照上述步骤解决并继续。

Constraints

限制条件

  • Stacks are strictly linear: one parent, at most one child. Use separate stacks for parallel work.
  • There is no non-interactive reorder or removal. Errors may suggest
    gh stack modify
    , but it is TUI-only; restructure with
    unstack
    then
    init
    instead.
  • PR titles and bodies are auto-generated. Use
    gh pr edit
    afterwards to change them.
  • checkout <branch-name>
    resolves against local stacks only. Use a stack or PR number to pull a stack down from GitHub.
  • 堆叠是严格线性的:每个分支只有一个父分支,最多一个子分支。并行工作请使用独立堆叠。
  • 不支持非交互式的重排序或移除操作。错误信息可能会建议使用
    gh stack modify
    ,但该命令仅支持TUI交互;请使用
    unstack
    后重新
    init
    来重构堆叠。
  • PR标题和描述是自动生成的。如需修改,请执行
    gh pr edit
  • checkout <branch-name>
    仅针对本地堆叠解析。如需从GitHub拉取堆叠,请使用堆叠编号或PR编号。

More detail

更多细节

gh stack <command> --help
is authoritative for flags and arguments (
gh stack help <command>
prints the top-level help instead). Read the reference that matches the task:
  • references/stack-design.md
    : before creating a stack, when deciding how many layers to use and what belongs in each.
  • references/commands.md
    : when a command fails unexpectedly or you need its preconditions, side effects, atomicity, or ordering guarantees.
  • references/troubleshooting.md
    : on a rebase conflict, after a squash-merge, on local and remote divergence, or when restructuring a stack.
gh stack <command> --help
是关于标志和参数的权威说明(
gh stack help <command>
会打印顶层帮助信息)。请根据任务阅读对应的参考文档:
  • references/stack-design.md
    :创建堆叠前,用于决定层级数量及每个层级的内容。
  • references/commands.md
    :当命令执行失败或你需要了解命令的前置条件、副作用、原子性或顺序保证时阅读。
  • references/troubleshooting.md
    :遇到rebase冲突、合并后、本地与远程分歧或重构堆叠时阅读。