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 managing stacked branches and pull requests. A stack is an ordered list of branches where each branch builds on the one below it, rooted on a trunk branch (typically the repo's default branch). Each branch maps to one PR whose base is the branch below it, so reviewers see only the diff for that layer.
main (trunk)
 └── feat/auth-layer     → PR #1 (base: main)               - bottom (closest to trunk)
  └── feat/api-endpoints → PR #2 (base: feat/auth-layer)
   └── feat/frontend     → PR #3 (base: feat/api-endpoints) - top (furthest from trunk)
The bottom of the stack is the branch closest to the trunk, and the top is the branch furthest from the trunk. Each branch inherits from the one below it. Navigation commands (
up
,
down
,
top
,
bottom
) follow this model:
up
moves away from trunk,
down
moves toward it.
gh stack
是一款用于管理**堆叠分支与拉取请求(PR)**的GitHub CLI扩展。堆叠分支是指一系列有序的分支,每个分支都基于其下方的分支构建,最终根源于主干分支(通常是仓库的默认分支)。每个分支对应一个PR,其基准分支为下方的分支,因此评审人员只能看到该层级的差异。
main (主干)
 └── feat/auth-layer     → PR #1 (基准: main)               - 底层(最接近主干)
  └── feat/api-endpoints → PR #2 (基准: feat/auth-layer)
   └── feat/frontend     → PR #3 (基准: feat/api-endpoints) - 顶层(最远离主干)
堆叠的底层是最接近主干的分支,顶层是最远离主干的分支。每个分支都继承自其下方的分支。导航命令(
up
down
top
bottom
)遵循此模型:
up
远离主干移动,
down
向主干移动。

When to use this skill

适用场景

Use this skill when the user wants to:
  • Break a large change into a chain of small, reviewable PRs
  • Create, rebase, push, or sync a stack of dependent branches
  • Navigate between layers of a branch stack
  • View the status of stacked PRs
  • Tear down and rebuild a stack to remove, reorder, or rename branches
当用户需要以下操作时使用该工具:
  • 将大型变更拆分为一系列小型、便于审查的PR
  • 创建、变基、推送或同步依赖型分支堆叠
  • 在分支堆叠的不同层级间导航
  • 查看堆叠PR的状态
  • 拆解并重建堆叠以移除、重新排序或重命名分支

Prerequisites

前置条件

The GitHub CLI (
gh
) v2.0+ must be installed and authenticated. Install the extension with:
bash
gh extension install github/gh-stack
Before using
gh stack
, configure git to prevent interactive prompts:
bash
git config rerere.enabled true           # remember conflict resolutions (skips prompt on init)
git config remote.pushDefault origin     # if multiple remotes exist (skips remote picker)
必须安装并认证GitHub CLI(
gh
)v2.0+。使用以下命令安装扩展:
bash
gh extension install github/gh-stack
在使用
gh stack
之前,配置git以避免交互式提示:
bash
git config rerere.enabled true           # 记住冲突解决方案(初始化时跳过提示)
git config remote.pushDefault origin     # 存在多个远程仓库时(跳过远程选择器)

Agent rules

Agent使用规则

All
gh stack
commands must be run non-interactively.
Every command invocation must include the flags and positional arguments needed to avoid prompts, TUIs, and interactive menus. If a command would prompt for input, it will hang indefinitely.
  1. Always supply branch names as positional arguments to
    init
    ,
    add
    , and
    checkout
    . Running these commands without arguments triggers interactive prompts.
  2. When a prefix is set, pass only the suffix to
    add
    .
    gh stack add auth
    with prefix
    feat
    feat/auth
    . Passing
    feat/auth
    creates
    feat/feat/auth
    .
  3. Always use
    --auto
    with
    gh stack submit
    to auto-generate PR titles. Without
    --auto
    ,
    submit
    prompts for a title for each new PR.
  4. Always use
    --json
    with
    gh stack view
    .
    Without
    --json
    , the command launches an interactive TUI that cannot be operated by agents. There is no other appropriate flag — always pass
    --json
    .
  5. Use
    --remote <name>
    when multiple remotes are configured
    , or pre-configure
    git config remote.pushDefault origin
    . Without this,
    push
    ,
    submit
    ,
    sync
    , and
    checkout
    trigger an interactive remote picker.
  6. Avoid branches shared across multiple stacks. If a branch belongs to multiple stacks, commands exit with code 6. Check out a non-shared branch first.
  7. Plan your stack layers by dependency order before writing code. Foundational changes (models, APIs, shared utilities) go in lower branches; dependent changes (UI, consumers) go in higher branches. Think through the dependency chain before running
    gh stack init
    .
  8. Use standard
    git add
    and
    git commit
    for staging and committing.
    This gives you full control over which changes go into each branch. The
    -Am
    shortcut is available but should not be the default approach—stacked PRs are most effective when each branch contains a deliberate, logical set of changes.
  9. Navigate down the stack when you need to change a lower layer. If you're working on a frontend branch and realize you need API changes, don't hack around it at the current layer. Navigate to the appropriate branch (
    gh stack down
    ,
    gh stack checkout
    , or
    gh stack bottom
    ), make and commit the changes there, run
    gh stack rebase --upstack
    , then navigate back up to continue.
Never do any of the following — each triggers an interactive prompt or TUI that will hang:
  • gh stack view
    or
    gh stack view --short
    — always use
    gh stack view --json
  • gh stack submit
    without
    --auto
    — always use
    gh stack submit --auto
  • gh stack init
    without branch arguments — always provide branch names
  • gh stack add
    without a branch name — always provide a branch name
  • gh stack checkout
    without an argument — always provide a PR number or branch name
  • gh stack checkout <pr-number>
    when a different local stack already exists on those branches — this triggers an unbypassable conflict resolution prompt; use
    gh stack unstack
    first to remove the local stack, then retry the checkout
所有
gh stack
命令必须以非交互方式运行。
每次命令调用必须包含所需的标志和位置参数,以避免提示、TUI和交互式菜单。如果命令会提示输入,将无限期挂起。
  1. 始终为
    init
    add
    checkout
    提供分支名称作为位置参数
    。不带参数运行这些命令会触发交互式提示。
  2. 设置前缀后,仅将后缀传递给
    add
    。例如,前缀为
    feat
    时,
    gh stack add auth
    会创建
    feat/auth
    。如果传递
    feat/auth
    ,则会创建
    feat/feat/auth
  3. **始终在
    gh stack submit
    中使用
    --auto
    **以自动生成PR标题。如果不带
    --auto
    submit
    会为每个新PR提示输入标题。
  4. 始终在
    gh stack view
    中使用
    --json
    。不带
    --json
    时,该命令会启动Agent无法操作的交互式TUI。没有其他合适的标志——必须始终传递
    --json
  5. 配置多个远程仓库时,使用
    --remote <name>
    ,或预先在git配置中设置
    remote.pushDefault origin
    。如果不这样做,
    push
    submit
    sync
    checkout
    会触发交互式远程选择器。
  6. 避免分支跨多个堆叠共享。如果一个分支属于多个堆叠,命令会以代码6退出。先切换到非共享分支。
  7. 在编写代码前按依赖顺序规划堆叠层级。基础变更(模型、API、共享工具)放在较低的分支中;依赖这些变更的代码放在较高的分支中。在运行
    gh stack init
    前仔细考虑依赖链。
  8. 使用标准的
    git add
    git commit
    进行暂存与提交
    。这样可以完全控制哪些变更进入哪个分支。
    -Am
    快捷方式可用,但不应作为默认方法——堆叠PR在每个分支包含一组明确、逻辑相关的变更时效果最佳。
  9. 需要修改底层分支时,导航到堆叠的下层。如果您在前端分支工作时意识到需要修改API,不要在当前层级临时处理。导航到相应的分支(
    gh stack down
    gh stack checkout
    gh stack bottom
    ),在那里进行并提交变更,运行
    gh stack rebase --upstack
    ,然后导航回上层继续工作。
绝对不要执行以下操作——每项操作都会触发交互式提示或TUI,导致挂起:
  • gh stack view
    gh stack view --short
    —— 始终使用
    gh stack view --json
  • gh stack submit
    不带
    --auto
    —— 始终使用
    gh stack submit --auto
  • gh stack init
    不带分支参数 —— 始终提供分支名称
  • gh stack add
    不带分支名称 —— 始终提供分支名称
  • gh stack checkout
    不带参数 —— 始终提供PR编号或分支名称
  • ❌ 当本地已有基于这些分支的不同堆叠时,运行
    gh stack checkout <pr-number>
    —— 这会触发无法绕过的冲突解决提示;先使用
    gh stack unstack
    移除本地堆叠,然后重试checkout

Thinking about stack structure

堆叠结构设计

Each branch in a stack should represent a discrete, logical unit of work that can be reviewed independently. The changes within a branch should be cohesive—they belong together and make sense as a single PR.
堆叠中的每个分支应代表一个独立、逻辑完整的工作单元,可独立进行审查。分支内的变更应具有内聚性——它们属于同一组,作为单个PR是合理的。

Dependency chain

依赖链

Stacked branches form a dependency chain: each branch builds on the one below it. This means foundational changes must go in lower (earlier) branches, and code that depends on them goes in higher (later) branches.
Plan your layers before writing code. For example, a full-stack feature might be structured like this (use branch names relevant to your actual task, not these generic ones):
main (trunk)
 └── feat/data-models    ← shared types, database schema
  └── feat/api-endpoints ← API routes that use the models
   └── feat/frontend-ui  ← UI components that call the APIs
    └── feat/integration ← tests that exercise the full stack
This is illustrative — choose branch names and layer boundaries that reflect the specific work you're doing. The key principle is: if code in one layer depends on code in another, the dependency must be in the same branch or a lower one.
堆叠分支形成依赖链:每个分支都基于其下方的分支构建。这意味着基础变更必须放在较低(较早)的分支中,依赖这些变更的代码放在较高(较晚)的分支中。
在编写代码前规划层级。例如,一个全栈功能的结构可能如下(使用与实际任务相关的分支名称,而非这些通用名称):
main (主干)
 └── feat/data-models    ← 共享类型、数据库模式
  └── feat/api-endpoints ← 使用模型的API路由
   └── feat/frontend-ui  ← 调用API的UI组件
    └── feat/integration ← 测试全栈功能
这只是示例——选择能反映具体工作的分支名称和层级边界。核心原则是:如果某一层级的代码依赖另一层级的代码,依赖项必须位于同一分支或更低层级的分支中。

Branch naming

分支命名

Prefer initializing stacks with a prefix (
-p
). Prefixes group branches under a namespace (e.g.,
feat/auth
,
feat/api
) and keep branch names clean and consistent. When a prefix is set, pass only the suffix to subsequent
add
calls — the prefix is applied automatically. Without a prefix, you'll need to pass the full branch name each time.
建议使用前缀(
-p
)初始化堆叠。前缀将分支分组到命名空间下(例如
feat/auth
feat/api
),保持分支名称清晰一致。设置前缀后,后续的
add
调用只需传递后缀——前缀会自动应用。如果没有前缀,每次都需要传递完整的分支名称。

Staging changes deliberately

谨慎暂存变更

The main reason to use
git add
and
git commit
directly is to control which changes go into which branch. When you have multiple files in your working tree, you can stage a subset for the current branch, commit them, then create a new branch and stage the rest there:
bash
undefined
直接使用
git add
git commit
的主要原因是控制哪些变更进入哪个分支。当工作区中有多个文件时,可以暂存当前分支的子集,提交它们,然后创建新分支并暂存剩余的文件:
bash
undefined

You're on feat/data-models with several new files in your working tree.

您当前在feat/data-models分支,工作区中有几个新文件。

Stage only the model files for this branch:

仅暂存此分支的模型文件:

git add internal/models/user.go internal/models/session.go git commit -m "Add user and session models"
git add db/migrations/001_create_users.sql git commit -m "Add user table migration"
git add internal/models/user.go internal/models/session.go git commit -m "Add user and session models"
git add db/migrations/001_create_users.sql git commit -m "Add user table migration"

Now create a new branch for the API layer and stage the API files there:

现在为API层创建新分支并暂存API文件:

gh stack add api-routes # created & switched to feat/api-routes branch git add internal/api/routes.go internal/api/handlers.go git commit -m "Add user API routes"

This keeps each branch focused on one concern. Multiple commits per branch are fine — the key is that all commits in a branch relate to the same logical concern, and changes that belong to a different concern go in a different branch.
gh stack add api-routes # 创建并切换到feat/api-routes分支 git add internal/api/routes.go internal/api/handlers.go git commit -m "Add user API routes"

这样可以保持每个分支专注于一个关注点。每个分支可以有多个提交——关键是分支中的所有提交都与同一逻辑关注点相关,属于不同关注点的变更应放在不同的分支中。

When to create a new branch

何时创建新分支

Create a new branch (
gh stack add
) when you're starting a different concern that depends on what you've built so far. Signs it's time for a new branch:
  • You're switching from backend to frontend work
  • You're moving from core logic to tests or documentation
  • The next set of changes has a different reviewer audience
  • The current branch's PR is already large enough to review
当您开始一个新的关注点且该关注点依赖于已完成的工作时,创建新分支(
gh stack add
)。表明需要新分支的迹象:
  • 您从后端工作切换到前端工作
  • 您从核心逻辑转向测试或文档
  • 下一组变更的受众 reviewer 不同
  • 当前分支的PR已经大到难以审查

One stack, one story

一个堆叠,一个故事

Think of a stack from the reviewer's perspective: the stack of PRs should tell a cohesive story about a feature or project. A reviewer should be able to read the PRs in sequence and understand the progression of changes, with each PR being a small, logical piece of the whole.
When to use a single stack: All the branches are part of the same feature, project, or closely related effort. Even if the work spans multiple concerns (models, API, frontend), they're all building toward the same goal.
When to create a separate stack: The work is unrelated to your current stack — a different feature, a bug fix in an unrelated area, or an independent refactor. Don't mix unrelated work into a single stack just because you happen to be working on both. Start a new stack with
gh stack init
or switch to an existing stack with
gh stack checkout
for each distinct effort.
Small, incidental fixes (e.g., fixing a typo you noticed) can go in the current stack if they're trivial. But if a change grows into its own project, it deserves its own stack.
从评审人员的角度考虑堆叠:PR堆叠应讲述一个连贯的功能或项目故事。评审人员应能够按顺序阅读PR,理解变更的进展,每个PR都是整体的一个小型、逻辑完整的部分。
何时使用单个堆叠: 所有分支都属于同一功能、项目或密切相关的工作。即使工作跨越多个关注点(模型、API、前端),它们都朝着同一个目标前进。
何时创建单独的堆叠: 工作与当前堆叠无关——例如不同的功能、无关领域的bug修复或独立的重构。不要仅仅因为您同时在处理两项工作就将无关工作混合到单个堆叠中。为每个不同的工作使用
gh stack init
创建新堆叠,或使用
gh stack checkout
切换到现有堆叠。
小型的偶然修复(例如您注意到的拼写错误)如果很琐碎,可以放在当前堆叠中。但如果变更发展成独立的项目,它应该有自己的堆叠。

Quick reference

快速参考

TaskCommand
Create a stack (recommended)
gh stack init -p feat auth
Create a stack without prefix
gh stack init auth
Adopt existing branches
gh stack init --adopt branch-a branch-b
Set custom trunk
gh stack init --base develop branch-a
Add a branch to stack (suffix only if prefix set)
gh stack add api-routes
Add branch + stage all + commit
gh stack add -Am "message" api-routes
Push branches to remote
gh stack push
Push to specific remote
gh stack push --remote origin
Push branches + create PRs
gh stack submit --auto
Create PRs as drafts
gh stack submit --auto --draft
Sync (fetch, rebase, push)
gh stack sync
Sync with specific remote
gh stack sync --remote origin
Rebase entire stack
gh stack rebase
Rebase upstack only
gh stack rebase --upstack
Continue after conflict
gh stack rebase --continue
Abort rebase
gh stack rebase --abort
View stack details (JSON)
gh stack view --json
Switch branches up/down in stack
gh stack up [n]
/
gh stack down [n]
Switch to top/bottom branch
gh stack top
/
gh stack bottom
Check out by PR
gh stack checkout 42
Check out by branch (local only)
gh stack checkout feature-auth
Tear down a stack to restructure it
gh stack unstack

任务命令
创建堆叠(推荐方式)
gh stack init -p feat auth
不带前缀创建堆叠
gh stack init auth
采用现有分支
gh stack init --adopt branch-a branch-b
设置自定义主干
gh stack init --base develop branch-a
向堆叠添加分支(设置前缀后仅传递后缀)
gh stack add api-routes
添加分支+暂存所有+提交
gh stack add -Am "message" api-routes
将分支推送到远程仓库
gh stack push
推送到指定远程仓库
gh stack push --remote origin
推送分支并创建PR
gh stack submit --auto
创建草稿PR
gh stack submit --auto --draft
同步(拉取、变基、推送)
gh stack sync
与指定远程仓库同步
gh stack sync --remote origin
变基整个堆叠
gh stack rebase
仅变基上层分支
gh stack rebase --upstack
解决冲突后继续
gh stack rebase --continue
中止变基
gh stack rebase --abort
查看堆叠详情(JSON格式)
gh stack view --json
在堆叠中向上/向下切换分支
gh stack up [n]
/
gh stack down [n]
切换到顶层/底层分支
gh stack top
/
gh stack bottom
通过PR编号切换
gh stack checkout 42
通过分支名称切换(仅本地)
gh stack checkout feature-auth
拆解堆叠以重构
gh stack unstack

Workflows

工作流程

End-to-end: create a stack from scratch

端到端:从头创建堆叠

bash
undefined
bash
undefined

1. Initialize a stack with the first branch

1. 使用第一个分支初始化堆叠

gh stack init -p feat auth
gh stack init -p feat auth

→ creates feat/auth and checks it out

→ 创建feat/auth并切换到该分支

2. Write code for the first layer (auth)

2. 为第一层(auth)编写代码

cat > auth.go << 'EOF' package auth
func Middleware(next http.Handler) http.Handler { return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { // verify token next.ServeHTTP(w, r) }) } EOF
cat > auth.go << 'EOF' package auth
func Middleware(next http.Handler) http.Handler { return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { // verify token next.ServeHTTP(w, r) }) } EOF

3. Stage and commit using standard git commands

3. 使用标准git命令暂存并提交

git add auth.go git commit -m "Add auth middleware"
git add auth.go git commit -m "Add auth middleware"

You can make multiple commits on the same branch

您可以在同一分支上进行多次提交

cat > auth_test.go << 'EOF' package auth
func TestMiddleware(t *testing.T) { // test auth middleware } EOF git add auth_test.go git commit -m "Add auth middleware tests"
cat > auth_test.go << 'EOF' package auth
func TestMiddleware(t *testing.T) { // test auth middleware } EOF git add auth_test.go git commit -m "Add auth middleware tests"

4. When you're ready for a new concern, add the next branch

4. 准备好处理新关注点时,添加下一个分支

gh stack add api-routes
gh stack add api-routes

→ creates feat/api-routes (prefix applied automatically — just pass the suffix)

→ 自动应用前缀,创建feat/api-routes

5. Write code for the API layer

5. 为API层编写代码

cat > api.go << 'EOF' package api
func RegisterRoutes(mux *http.ServeMux) { mux.HandleFunc("/users", handleUsers) } EOF git add api.go git commit -m "Add API routes"
cat > api.go << 'EOF' package api
func RegisterRoutes(mux *http.ServeMux) { mux.HandleFunc("/users", handleUsers) } EOF git add api.go git commit -m "Add API routes"

6. Add a third layer for frontend

6. 添加第三层用于前端

gh stack add frontend
gh stack add frontend

→ creates feat/frontend (just the suffix — prefix is automatic)

→ 自动应用前缀,创建feat/frontend

cat > frontend.go << 'EOF' package frontend
func RenderDashboard(w http.ResponseWriter) { // calls the API endpoints from the layer below } EOF git add frontend.go git commit -m "Add frontend dashboard"
cat > frontend.go << 'EOF' package frontend
func RenderDashboard(w http.ResponseWriter) { // calls the API endpoints from the layer below } EOF git add frontend.go git commit -m "Add frontend dashboard"

── Stack complete: feat/auth → feat/api-routes → feat/frontend ──

── 堆叠完成:feat/auth → feat/api-routes → feat/frontend ──

7. Push everything and create draft PRs

7. 推送所有内容并创建草稿PR

gh stack submit --auto --draft
gh stack submit --auto --draft

8. Verify the stack

8. 验证堆叠

gh stack view --json

> **Shortcut:** If you prefer a faster flow, `gh stack add -Am "message" branch-name` combines staging, committing, and branch creation into one command. This is useful for single-commit layers but bypasses deliberate staging.
gh stack view --json

> **快捷方式:** 如果您更喜欢更快的流程,`gh stack add -Am "message" branch-name`将暂存、提交和分支创建合并为一个命令。这适用于单提交层级,但会跳过谨慎的暂存步骤。

Making mid-stack changes

对堆叠中层进行修改

This is a critical workflow for agents. When you're working on a higher layer and realize you need to change something in a lower layer (e.g., you're building frontend components but need to add an API endpoint), navigate down to the correct branch, make the change there, and rebase.
bash
undefined
这是Agent的关键工作流程。当您在较高层级工作时,意识到需要修改较低层级的内容(例如,您正在构建前端组件,但需要添加一个API端点),导航到正确的分支,在那里进行修改,然后变基
bash
undefined

You're on feat/frontend but need to add an API endpoint

您当前在feat/frontend分支,但需要添加一个API端点

1. Navigate to the API branch

1. 导航到API分支

gh stack down
gh stack down

or: gh stack checkout feat/api-routes

或:gh stack checkout feat/api-routes

2. Make the change where it belongs

2. 在合适的位置进行修改

cat > users_api.go << 'EOF' package api
func handleGetUser(w http.ResponseWriter, r *http.Request) { // new endpoint the frontend needs } EOF git add users_api.go git commit -m "Add get-user endpoint"
cat > users_api.go << 'EOF' package api
func handleGetUser(w http.ResponseWriter, r *http.Request) { // new endpoint the frontend needs } EOF git add users_api.go git commit -m "Add get-user endpoint"

3. Rebase everything above to pick up the change

3. 变基所有上层分支以获取变更

gh stack rebase --upstack
gh stack rebase --upstack

4. Navigate back to where you were working

4. 导航回之前工作的分支

gh stack top
gh stack top

or: gh stack checkout feat/frontend

或:gh stack checkout feat/frontend

5. Continue working — the API changes are now available

5. 继续工作——API变更现在可用


**Why this matters:** If you make API changes on the frontend branch, those changes will end up in the wrong PR. The API PR won't include them, and the frontend PR will have unrelated API diffs mixed in. Always put changes in the branch where they logically belong.

**为什么这很重要:** 如果您在前端分支上进行API变更,这些变更会进入错误的PR。API PR不会包含它们,而前端PR会混合无关的API差异。始终将变更放在逻辑上所属的分支中。

Modify a mid-stack branch and sync

修改堆叠中层分支并同步

When you need to revisit a branch after the initial creation (e.g., responding to review feedback):
bash
undefined
当初始创建后需要重新访问分支时(例如,响应审查反馈):
bash
undefined

1. Navigate to the branch that needs changes

1. 导航到需要修改的分支

gh stack bottom
gh stack bottom

or: gh stack checkout feat/auth

或:gh stack checkout feat/auth

or: gh stack checkout 42 (by PR number)

或:gh stack checkout 42 (通过PR编号)

2. Make changes and commit

2. 进行修改并提交

cat > auth.go << 'EOF' package auth // updated implementation EOF git add auth.go git commit -m "Fix auth token validation"
cat > auth.go << 'EOF' package auth // updated implementation EOF git add auth.go git commit -m "Fix auth token validation"

3. Rebase everything above this branch

3. 变基此分支上方的所有分支

gh stack rebase --upstack
gh stack rebase --upstack

4. Push the updated stack

4. 推送更新后的堆叠

gh stack push
undefined
gh stack push
undefined

Routine sync after merges

合并后的例行同步

bash
undefined
bash
undefined

Single command: fetch, rebase, push, sync PR state

单个命令:拉取、变基、推送、同步PR状态

gh stack sync
undefined
gh stack sync
undefined

Squash-merge recovery

squash合并恢复

When a PR is squash-merged on GitHub, the original branch's commits no longer exist in the trunk history.
gh stack
detects this automatically and uses
git rebase --onto
to correctly replay remaining commits.
bash
undefined
当PR在GitHub上被squash合并后,原始分支的提交不再存在于主干历史中。
gh stack
会自动检测到这一点,并使用
git rebase --onto
正确重放剩余的提交。
bash
undefined

After PR #1 (feat/auth) is squash-merged on GitHub:

PR #1(feat/auth)在GitHub上被squash合并后:

gh stack sync
gh stack sync

→ fetches latest, detects the merge, fast-forwards trunk

→ 拉取最新变更,检测到合并,快进主干

→ rebases feat/api-routes onto updated trunk (skips merged branch)

→ 将feat/api-routes变基到更新后的主干(跳过已合并的分支)

→ rebases feat/frontend onto feat/api-routes

→ 将feat/frontend变基到feat/api-routes

→ pushes updated branches

→ 推送更新后的分支

→ reports: "Merged: #1"

→ 报告:"Merged: #1"

Verify the result

验证结果

gh stack view --json
gh stack view --json

→ feat/auth shows "isMerged": true, "state": "MERGED"

→ feat/auth显示"isMerged": true, "state": "MERGED"

→ feat/api-routes and feat/frontend show updated heads

→ feat/api-routes和feat/frontend显示更新后的头部


If `sync` hits a conflict during this process, it restores all branches to their pre-rebase state and exits with code 3. See [Handle rebase conflicts](#handle-rebase-conflicts-agent-workflow) for the resolution workflow.

如果`sync`在此过程中遇到冲突,会将所有分支恢复到变基前的状态并以代码3退出。请参阅[处理变基冲突](#处理变基冲突-agent-workflow)了解解决流程。

Handle rebase conflicts (agent workflow)

处理变基冲突(Agent工作流程)

bash
undefined
bash
undefined

1. Start the rebase

1. 开始变基

gh stack rebase
gh stack rebase

2. If exit code 3 (conflict):

2. 如果退出代码为3(冲突):

- Parse stderr for conflicted file paths

- 解析stderr中的冲突文件路径

- Read those files to find <<<<<<< / ======= / >>>>>>> markers

- 读取这些文件以找到<<<<<<< / ======= / >>>>>>>标记

- Edit files to resolve conflicts

- 编辑文件以解决冲突

- Stage resolved files:

- 暂存已解决的文件:

git add path/to/resolved-file.go
git add path/to/resolved-file.go

3. Continue the rebase

3. 继续变基

gh stack rebase --continue
gh stack rebase --continue

4. If another conflict occurs, repeat steps 2-3

4. 如果再次发生冲突,重复步骤2-3

5. If unable to resolve, abort to restore everything

5. 如果无法解决,中止以恢复所有内容

gh stack rebase --abort
undefined
gh stack rebase --abort
undefined

Parsing
--json
output

解析
--json
输出

bash
undefined
bash
undefined

Get stack state as JSON

获取JSON格式的堆叠状态

output=$(gh stack view --json)
output=$(gh stack view --json)

Check if any branch needs a rebase, and rebase if so

检查是否有分支需要变基,如果有则进行变基

needs_rebase=$(echo "$output" | jq '[.branches[] | select(.needsRebase == true)] | length') if [ "$needs_rebase" -gt 0 ]; then echo "Branches need rebase, rebasing stack..." gh stack rebase fi
needs_rebase=$(echo "$output" | jq '[.branches[] | select(.needsRebase == true)] | length') if [ "$needs_rebase" -gt 0 ]; then echo "Branches need rebase, rebasing stack..." gh stack rebase fi

Get all open PR URLs

获取所有开放PR的URL

echo "$output" | jq -r '.branches[] | select(.pr.state == "OPEN") | .pr.url'
echo "$output" | jq -r '.branches[] | select(.pr.state == "OPEN") | .pr.url'

Find merged branches

查找已合并的分支

echo "$output" | jq -r '.branches[] | select(.isMerged == true) | .name'
echo "$output" | jq -r '.branches[] | select(.isMerged == true) | .name'

Get the current branch

获取当前分支

echo "$output" | jq -r '.currentBranch'
echo "$output" | jq -r '.currentBranch'

Check if the stack is fully merged (all branches merged)

检查堆叠是否完全合并(所有分支都已合并)

echo "$output" | jq '[.branches[] | .isMerged] | all'
undefined
echo "$output" | jq '[.branches[] | .isMerged] | all'
undefined

Restructure a stack (remove a branch, reorder, or rename)

重构堆叠(移除分支、重新排序或重命名)

Use
unstack
to tear down the stack, make structural changes, then re-init:
bash
undefined
使用
unstack
拆解堆叠,进行结构性修改,然后重新初始化:
bash
undefined

1. Remove the stack (locally and on GitHub)

1. 移除堆叠(本地和GitHub上),然后重建

gh stack unstack
gh stack unstack gh stack init --base main --adopt new-branch-1 new-branch-2 new-branch-3 # 重新排序

2. Make structural changes — e.g. delete a branch, reorder, rename

仅移除本地跟踪(保留GitHub上的堆叠)

git branch -m old-branch-1 new-branch-1
gh stack unstack --local

3. Re-create the stack with the new structure

指定分支以确定要拆解的堆叠

gh stack init --base main --adopt new-branch-1 new-branch-2 new-branch-3

---
gh stack unstack feature-auth

---

Commands

命令详解

Initialize a stack —
gh stack init

初始化堆叠 —
gh stack init

Creates a new stack. Always provide at least one branch name as a positional argument — running without branch arguments triggers interactive prompts that agents cannot use.
gh stack init [flags] <branches...>
bash
undefined
创建新堆叠。始终至少提供一个分支名称作为位置参数——不带分支参数运行会触发Agent无法使用的交互式提示。
gh stack init [flags] <branches...>
bash
undefined

Set a branch prefix (recommended — subsequent
add
calls only need the suffix)

设置分支前缀(推荐——后续
add
调用只需传递后缀)

gh stack init -p feat auth
gh stack init -p feat auth

→ creates feat/auth

→ 创建feat/auth

Multi-part prefix (slashes are fine — suffix-only rule still applies)

多部分前缀(支持斜杠——仍适用仅传递后缀的规则)

gh stack init -p monalisa/billing auth
gh stack init -p monalisa/billing auth

→ creates monalisa/billing/auth

→ 创建monalisa/billing/auth

Create a stack with new branches (no prefix — use full branch names)

创建新分支堆叠(不带前缀——使用完整分支名称)

gh stack init branch-a branch-b branch-c
gh stack init branch-a branch-b branch-c

Use a different trunk branch

使用不同的主干分支

gh stack init --base develop branch-a branch-b
gh stack init --base develop branch-a branch-b

Adopt existing branches into a stack

采用现有分支到堆叠中

gh stack init --adopt branch-a branch-b branch-c

| Flag | Description |
|------|-------------|
| `-b, --base <branch>` | Trunk branch (defaults to the repo's default branch) |
| `-a, --adopt` | Adopt existing branches instead of creating new ones |
| `-p, --prefix <string>` | Branch name prefix. Subsequent `add` calls only need the suffix (e.g., with `-p feat`, `gh stack add auth` creates `feat/auth`) |

**Behavior:**

- Using `-p` is recommended — it simplifies branch naming for subsequent `add` calls
- Creates any branches that don't already exist (branching from the trunk branch)
- In `--adopt` mode: validates all branches exist, rejects if any is already in a stack or has an existing PR
- Checks out the last branch in the list
- Enables `git rerere` so conflict resolutions are remembered across rebases. On first run in a repo, this may trigger a confirmation prompt — pre-configure with `git config rerere.enabled true` to avoid it

---
gh stack init --adopt branch-a branch-b branch-c

| 标志 | 描述 |
|------|-------------|
| `-b, --base <branch>` | 主干分支(默认为仓库的默认分支) |
| `-a, --adopt` | 采用现有分支而非创建新分支 |
| `-p, --prefix <string>` | 分支名称前缀。后续`add`调用只需传递后缀(例如,前缀为`feat`时,`gh stack add auth`会创建`feat/auth`) |

**行为:**

- 推荐使用`-p`——简化后续`add`调用的分支命名
- 创建任何不存在的分支(基于主干分支创建)
- 在`--adopt`模式下:验证所有分支是否存在,如果任何分支已属于某个堆叠或已有PR则拒绝
- 切换到列表中的最后一个分支
- 启用`git rerere`以便在变基时记住冲突解决方案。在仓库中首次运行时,可能会触发确认提示——预先配置`git config rerere.enabled true`以避免。

---

Add a branch —
gh stack add

添加分支 —
gh stack add

Add a new branch on top of the current stack. Must be run while on the topmost branch (or the trunk if the stack has no branches yet). Always provide a branch name — running without one triggers an interactive prompt.
gh stack add [flags] <branch>
Recommended workflow — create the branch, then use standard git:
bash
undefined
在当前堆叠的顶部添加新分支。必须在最顶层分支(或堆叠为空时的主干分支)上运行。始终提供分支名称——不带参数运行会触发交互式提示。
gh stack add [flags] <branch>
推荐工作流程 — 创建分支,然后使用标准git命令:
bash
undefined

Create a new branch and switch to it (just the suffix — prefix is applied automatically)

创建新分支并切换到该分支(仅传递后缀——前缀会自动应用)

gh stack add api-routes
gh stack add api-routes

Write code, stage deliberately, and commit

编写代码,谨慎暂存并提交

git add internal/api/routes.go internal/api/handlers.go git commit -m "Add user API routes"
git add internal/api/routes.go internal/api/handlers.go git commit -m "Add user API routes"

Make more commits on the same branch as needed

根据需要在同一分支上进行更多提交

git add internal/api/middleware.go git commit -m "Add rate limiting middleware"

**Shortcut — stage, commit, and branch in one command:**

```bash
git add internal/api/middleware.go git commit -m "Add rate limiting middleware"

**快捷方式 — 暂存、提交和分支创建一步完成:**

```bash

Create a new branch, stage all changes, and commit

创建新分支,暂存所有变更并提交

gh stack add -Am "Add API routes" api-routes
gh stack add -Am "Add API routes" api-routes

Create a new branch, stage tracked files only, and commit

创建新分支,仅暂存已跟踪文件并提交

gh stack add -um "Fix auth bug" auth-fix

| Flag | Description |
|------|-------------|
| `-m, --message <string>` | Create a commit with this message |
| `-A, --all` | Stage all changes including untracked files (requires `-m`) |
| `-u, --update` | Stage tracked files only (requires `-m`) |

**Behavior notes:**

- `-A` and `-u` are mutually exclusive.
- When the current branch has no commits (e.g., right after `init`), `add -Am` commits directly on the current branch instead of creating a new one.
- **Prefix handling:** Only pass the suffix when a prefix is set. `gh stack add api` with prefix `todo` → `todo/api`. Passing `todo/api` creates `todo/todo/api`. Without a prefix, pass the full branch name.
- If called from a branch that is not the topmost in the stack, exits with code 5: `"can only add branches on top of the stack"`. Use `gh stack top` to switch first.
- **Uncommitted changes:** When using `gh stack add branch-name` without `-Am`, any uncommitted changes (staged or unstaged) in your working tree carry over to the new branch. This is standard git behavior — the working tree is not touched. Commit or stash changes on the current branch before running `add` if you want a clean starting point on the new branch.

---
gh stack add -um "Fix auth bug" auth-fix

| 标志 | 描述 |
|------|-------------|
| `-m, --message <string>` | 使用此消息创建提交 |
| `-A, --all` | 暂存所有变更,包括未跟踪文件(需要`-m`) |
| `-u, --update` | 仅暂存已跟踪文件(需要`-m`) |

**行为说明:**

- `-A`和`-u`互斥。
- 当当前分支没有提交时(例如,刚运行`init`后),`add -Am`会直接在当前分支上提交,而不是创建新分支。
- **前缀处理:** 设置前缀后仅传递后缀。前缀为`todo`时,`gh stack add api`会创建`todo/api`。如果传递`todo/api`,则会创建`todo/todo/api`。不带前缀时,传递完整分支名称。
- 如果从堆叠中非顶层的分支调用,会以代码5退出:`"can only add branches on top of the stack"`。先使用`gh stack top`切换到顶层分支。
- **未提交的变更:** 使用`gh stack add branch-name`而不带`-Am`时,工作区中所有未提交的变更(已暂存或未暂存)会被带到新分支中。这是标准的git行为——工作区不会被修改。如果希望新分支有一个干净的起点,在运行`add`之前提交或暂存当前分支的变更。

---

Push branches to remote —
gh stack push

推送分支到远程仓库 —
gh stack push

Push all stack branches to the remote.
gh stack push [flags]
bash
undefined
将所有堆叠分支推送到远程仓库。
gh stack push [flags]
bash
undefined

Push all branches

推送所有分支

gh stack push
gh stack push

Push to specific remote

推送到指定远程仓库

gh stack push --remote upstream

| Flag | Description |
|------|-------------|
| `--remote <name>` | Remote to push to (use if multiple remotes exist) |

**Behavior:**

- Pushes all active (non-merged) branches atomically (`--force-with-lease --atomic`)
- Does **not** create or update pull requests — use `gh stack submit` for that

**Output (stderr):**

- `Pushed N branches` summary

---
gh stack push --remote upstream

| 标志 | 描述 |
|------|-------------|
| `--remote <name>` | 要推送的远程仓库(存在多个远程仓库时使用) |

**行为:**

- 以原子方式推送所有活动(未合并)分支(`--force-with-lease --atomic`)
- **不会**创建或更新拉取请求——使用`gh stack submit`进行此操作

**输出(stderr):**

- `Pushed N branches` 摘要

---

Submit branches and create PRs —
gh stack submit

提交分支并创建PR —
gh stack submit

Push all stack branches and create PRs on GitHub. Always pass
--auto
— without it,
submit
prompts for a PR title for each new branch.
bash
undefined
推送所有堆叠分支并在GitHub上创建PR。始终传递
--auto
——不带
--auto
时,
submit
会为每个新分支提示输入PR标题。
bash
undefined

Submit and auto-title new PRs (required for non-interactive use)

提交并自动生成新PR的标题(非交互使用必需)

gh stack submit --auto
gh stack submit --auto

Submit and create PRs as drafts

提交并创建草稿PR

gh stack submit --auto --draft

| Flag | Description |
|------|-------------|
| `--auto` | Auto-generate PR titles without prompting (**required** for non-interactive use) |
| `--draft` | Create new PRs as drafts |
| `--remote <name>` | Remote to push to (use if multiple remotes exist) |

**Behavior:**

- Pushes all active (non-merged) branches atomically (`--force-with-lease --atomic`)
- Creates a new PR for each branch that doesn't have one (base set to the first non-merged ancestor branch)
- After creating PRs, links them together as a **Stack** on GitHub (requires the repository to have stacks enabled)
- Syncs PR metadata for branches that already have PRs

**PR title auto-generation (`--auto`):**

- Single commit on branch → uses the commit subject as the PR title, commit body as PR body
- Multiple commits on branch → humanizes the branch name (hyphens/underscores → spaces) as the title

**Output (stderr):**

- `Created PR #N for <branch>` for each newly created PR
- `PR #N for <branch> is up to date` for existing PRs
- `Pushed and synced N branches` summary

---
gh stack submit --auto --draft

| 标志 | 描述 |
|------|-------------|
| `--auto` | 自动生成PR标题而不提示(**非交互使用必需**) |
| `--draft` | 将新PR创建为草稿 |
| `--remote <name>` | 要推送的远程仓库(存在多个远程仓库时使用) |

**行为:**

- 以原子方式推送所有活动(未合并)分支(`--force-with-lease --atomic`)
- 为每个没有PR的分支创建新PR(基准分支设置为第一个未合并的祖先分支)
- 创建PR后,在GitHub上将它们链接为一个**Stack**(需要仓库启用堆叠功能)
- 为已有PR的分支同步PR元数据

**PR标题自动生成(`--auto`):**

- 分支上有单个提交 → 使用提交主题作为PR标题,提交正文作为PR正文
- 分支上有多个提交 → 将分支名称人性化(连字符/下划线转换为空格)作为标题

**输出(stderr):**

- 每个新创建的PR显示`Created PR #N for <branch>`
- 已有PR显示`PR #N for <branch> is up to date`
- 摘要显示`Pushed and synced N branches`

---

Sync the stack —
gh stack sync

同步堆叠 —
gh stack sync

Fetch, rebase, push, and sync PR state in a single command. This is the recommended command for routine synchronization.
gh stack sync [flags]
FlagDescription
--remote <name>
Remote to fetch from and push to (use if multiple remotes exist)
What it does (in order):
  1. Fetch latest changes from the remote
  2. Fast-forward trunk to match remote (skips if already up to date, warns if diverged)
  3. Cascade rebase all stack branches onto their updated parents (only if trunk moved). Handles squash-merged PRs automatically. If a conflict is detected, all branches are restored to their pre-rebase state and the command exits with code 3 — see Handle rebase conflicts for the resolution workflow
  4. Push all active branches atomically
  5. Sync PR state from GitHub and report the status of each PR
Output (stderr):
  • ✓ Fetched latest changes from origin
  • ✓ Trunk main fast-forwarded to <sha>
    or
    ✓ Trunk main is already up to date
  • ✓ Rebased <branch> onto <base>
    per branch (if base moved)
  • ✓ Pushed N branches
  • ✓ PR #N (<branch>) — Open
    per branch
  • Merged: #N, #M
    for merged branches
  • ✓ Stack synced

在单个命令中完成拉取、变基、推送和同步PR状态。这是例行同步的推荐命令。
gh stack sync [flags]
标志描述
--remote <name>
要拉取和推送的远程仓库(存在多个远程仓库时使用)
执行步骤(按顺序):
  1. 拉取远程仓库的最新变更
  2. 快进主干以匹配远程仓库(如果已经是最新则跳过,如果分叉则发出警告)
  3. 级联变基所有堆叠分支到其更新后的父分支(仅在主干移动时)。自动处理squash合并的PR。如果检测到冲突,所有分支都会恢复到变基前的状态,命令以代码3退出——请参阅处理变基冲突了解解决流程
  4. 以原子方式推送所有活动分支
  5. 从GitHub同步PR状态并报告每个PR的状态
输出(stderr):
  • ✓ Fetched latest changes from origin
  • ✓ Trunk main fast-forwarded to <sha>
    ✓ Trunk main is already up to date
  • 每个分支显示
    ✓ Rebased <branch> onto <base>
    (如果基准分支移动)
  • ✓ Pushed N branches
  • 每个分支显示
    ✓ PR #N (<branch>) — Open
  • 已合并的分支显示
    Merged: #N, #M
  • ✓ Stack synced

Rebase the stack —
gh stack rebase

变基堆叠 —
gh stack rebase

Pull from remote and cascade-rebase stack branches. Use this when
sync
reports a conflict or when you need finer control (e.g., rebase only part of the stack).
gh stack rebase [flags] [branch]
bash
undefined
从远程仓库拉取并级联变基堆叠分支。当
sync
报告冲突或需要更精细的控制(例如,仅变基堆叠的一部分)时使用此命令。
gh stack rebase [flags] [branch]
bash
undefined

Rebase the entire stack

变基整个堆叠

gh stack rebase
gh stack rebase

Rebase only branches from trunk to current branch

仅变基从主干到当前分支的分支

gh stack rebase --downstack
gh stack rebase --downstack

Rebase only branches from current branch to top

仅变基从当前分支到顶层的分支

gh stack rebase --upstack
gh stack rebase --upstack

After resolving a conflict: stage files with
git add
, then:

解决冲突后:使用
git add
暂存文件,然后:

gh stack rebase --continue
gh stack rebase --continue

Abort and restore all branches to pre-rebase state

中止并将所有分支恢复到变基前的状态

gh stack rebase --abort

| Flag | Description |
|------|-------------|
| `--downstack` | Only rebase branches from trunk to the current branch |
| `--upstack` | Only rebase branches from the current branch to the top |
| `--continue` | Continue after resolving conflicts |
| `--abort` | Abort and restore all branches |
| `--remote <name>` | Remote to fetch from (use if multiple remotes exist) |

| Argument | Description |
|----------|-------------|
| `[branch]` | Target branch (defaults to the current branch) |

**Conflict handling:** See [Handle rebase conflicts](#handle-rebase-conflicts-agent-workflow) in the Workflows section for the full resolution workflow.

**Squash-merge detection:** If a branch's PR was squash-merged on GitHub, the rebase automatically handles this and correctly replays commits on top of the merge target.

**Rerere (conflict memory):** `git rerere` is enabled by `init` so previously resolved conflicts are auto-resolved in future rebases.

---
gh stack rebase --abort

| 标志 | 描述 |
|------|-------------|
| `--downstack` | 仅变基从主干到当前分支的分支 |
| `--upstack` | 仅变基从当前分支到顶层的分支 |
| `--continue` | 解决冲突后继续变基 |
| `--abort` | 中止并恢复所有分支 |
| `--remote <name>` | 要拉取的远程仓库(存在多个远程仓库时使用) |

| 参数 | 描述 |
|----------|-------------|
| `[branch]` | 目标分支(默认为当前分支) |

**冲突处理:** 请参阅工作流程部分的[处理变基冲突](#处理变基冲突-agent-workflow)了解完整的解决流程。

**Squash合并检测:** 如果分支的PR在GitHub上被squash合并,变基会自动处理此情况,并在合并目标上正确重放提交。

**Rerere(冲突记忆):** `init`命令启用了`git rerere`,因此之前解决的冲突会在未来的变基中自动解决。

---

View the stack —
gh stack view

查看堆叠 —
gh stack view

Display the current stack's branches, PR status, and recent commits. Always pass
--json
— without it, this command launches an interactive TUI that agents cannot operate.
bash
undefined
显示当前堆叠的分支、PR状态和最近的提交。始终传递
--json
——不带
--json
时,此命令会启动Agent无法操作的交互式TUI。
bash
undefined

Always use --json

始终使用--json

gh stack view --json

| Flag | Description |
|------|-------------|
| `--json` | Output stack data as JSON to stdout (**required** for non-interactive use) |

**`--json` output format:**

```json
{
  "trunk": "main",
  "prefix": "feat",
  "currentBranch": "feat/api-routes",
  "branches": [
    {
      "name": "feat/auth",
      "head": "abc1234...",
      "base": "def5678...",
      "isCurrent": false,
      "isMerged": true,
      "needsRebase": false,
      "pr": {
        "number": 42,
        "url": "https://github.com/owner/repo/pull/42",
        "state": "MERGED"
      }
    },
    {
      "name": "feat/api-routes",
      "head": "789abcd...",
      "base": "abc1234...",
      "isCurrent": true,
      "isMerged": false,
      "needsRebase": false,
      "pr": {
        "number": 43,
        "url": "https://github.com/owner/repo/pull/43",
        "state": "OPEN"
      }
    }
  ]
}
Fields per branch:
  • name
    — branch name
  • head
    — current HEAD SHA
  • base
    — parent branch's HEAD SHA at last sync
  • isCurrent
    — whether this is the checked-out branch
  • isMerged
    — whether the PR has been merged
  • needsRebase
    — whether the base branch is not an ancestor (non-linear history)
  • pr
    — PR metadata (omitted if no PR exists).
    state
    is
    "OPEN"
    or
    "MERGED"
    .

gh stack view --json

| 标志 | 描述 |
|------|-------------|
| `--json` | 以JSON格式输出堆叠数据到stdout(**非交互使用必需**) |

**`--json`输出格式:**

```json
{
  "trunk": "main",
  "prefix": "feat",
  "currentBranch": "feat/api-routes",
  "branches": [
    {
      "name": "feat/auth",
      "head": "abc1234...",
      "base": "def5678...",
      "isCurrent": false,
      "isMerged": true,
      "needsRebase": false,
      "pr": {
        "number": 42,
        "url": "https://github.com/owner/repo/pull/42",
        "state": "MERGED"
      }
    },
    {
      "name": "feat/api-routes",
      "head": "789abcd...",
      "base": "abc1234...",
      "isCurrent": true,
      "isMerged": false,
      "needsRebase": false,
      "pr": {
        "number": 43,
        "url": "https://github.com/owner/repo/pull/43",
        "state": "OPEN"
      }
    }
  ]
}
每个分支的字段:
  • name
    — 分支名称
  • head
    — 当前HEAD的SHA
  • base
    — 上次同步时父分支的HEAD SHA
  • isCurrent
    — 是否为当前检出的分支
  • isMerged
    — PR是否已合并
  • needsRebase
    — 基准分支是否不是祖先(非线性历史)
  • pr
    — PR元数据(如果没有PR则省略)。
    state
    "OPEN"
    "MERGED"

Navigate the stack

堆叠导航

Move between branches without remembering branch names. These commands are fully non-interactive.
bash
gh stack up          # Move up one branch (further from trunk)
gh stack up 3        # Move up three branches
gh stack down        # Move down one branch (closer to trunk)
gh stack down 2      # Move down two branches
gh stack top         # Jump to the top of the stack (furthest from trunk)
gh stack bottom      # Jump to the bottom (first non-merged branch above trunk)
Navigation clamps to stack bounds. Merged branches are skipped when navigating from active branches.

无需记住分支名称即可在分支间移动。这些命令完全是非交互式的。
bash
gh stack up          # 向上移动一个分支(远离主干)
gh stack up 3        # 向上移动三个分支
gh stack down        # 向下移动一个分支(靠近主干)
gh stack down 2      # 向下移动两个分支
gh stack top         # 跳转到堆叠的顶层(最远离主干)
gh stack bottom      # 跳到底层(主干上方的第一个未合并分支)
导航会限制在堆叠范围内。从活动分支导航时会跳过已合并的分支。

Check out a stack —
gh stack checkout

检出堆叠 —
gh stack checkout

Check out a stack from a pull request number or branch name. Always provide an argument — running
gh stack checkout
without arguments triggers an interactive selection menu.
gh stack checkout <pr-number | branch>
bash
undefined
通过拉取请求编号或分支名称检出堆叠。始终提供参数——不带参数运行
gh stack checkout
会触发交互式选择菜单。
gh stack checkout <pr-number | branch>
bash
undefined

By PR number (pulls from GitHub)

通过PR编号(从GitHub拉取)

gh stack checkout 42
gh stack checkout 42

By branch name (local only)

通过分支名称(仅本地)

gh stack checkout feature-auth

When a PR number is provided (e.g. `123`), the command fetches the stack on GitHub, pulls the branches, and sets up the stack locally. If the stack already exists locally and matches, it switches to the branch.

> **⚠️ Agent warning:** If the local and remote stacks have different branch compositions, this command triggers an interactive conflict-resolution prompt that cannot be bypassed with a flag. To avoid this: run `gh stack unstack` first to remove the conflicting local stack, then retry `gh stack checkout <pr-number>`.

When a branch name is provided, the command resolves it against locally tracked stacks only. This is always safe for non-interactive use.

---
gh stack checkout feature-auth

提供PR编号时(例如`123`),命令会在GitHub上获取堆叠,拉取分支,并在本地设置堆叠。如果堆叠已在本地存在且匹配,则切换到该分支。

> **⚠️ Agent警告:** 如果本地和远程堆叠的分支组成不同,此命令会触发交互式冲突解决提示,无法使用标志绕过。为避免这种情况:先运行`gh stack unstack`移除冲突的本地堆叠,然后重试`gh stack checkout <pr-number>`。

提供分支名称时,命令仅解析本地跟踪的堆叠。这对于非交互使用始终是安全的。

---

Remove a stack —
gh stack unstack

移除堆叠 —
gh stack unstack

Tear down a stack so you can restructure it — remove a branch, reorder branches, rename branches, or make other large changes. After unstacking, use
gh stack init
to re-create the stack with the desired structure.
gh stack unstack [flags] [branch]
bash
undefined
拆解堆叠以便重构——移除分支、重新排序分支、重命名分支或进行其他大型修改。拆解后,使用
gh stack init
以所需结构重新创建堆叠。
gh stack unstack [flags] [branch]
bash
undefined

Tear down the stack (locally and on GitHub), then rebuild

拆解堆叠(本地和GitHub上),然后重建

gh stack unstack gh stack init --base main --adopt branch-2 branch-1 branch-3 # reordered
gh stack unstack gh stack init --base main --adopt new-branch-1 new-branch-2 new-branch-3 # 重新排序

Only remove local tracking (keep the stack on GitHub)

仅移除本地跟踪(保留GitHub上的堆叠)

gh stack unstack --local
gh stack unstack --local

Specify a branch to identify which stack to tear down

指定分支以确定要拆解的堆叠

gh stack unstack feature-auth

| Flag | Description |
|------|-------------|
| `--local` | Only delete the stack locally (keep it on GitHub) |

| Argument | Description |
|----------|-------------|
| `[branch]` | A branch in the stack (defaults to the current branch) |

---
gh stack unstack feature-auth

| 标志 | 描述 |
|------|-------------|
| `--local` | 仅在本地删除堆叠(保留GitHub上的堆叠) |

| 参数 | 描述 |
|----------|-------------|
| `[branch]` | 堆叠中的一个分支(默认为当前分支) |

---

Output conventions

输出约定

  • Status messages go to stderr with emoji prefixes:
    (success),
    (error),
    (warning),
    (info).
  • Data output (e.g.,
    view --json
    ) goes to stdout.
  • When piping output, use
    2>/dev/null
    to suppress status messages if only data output is needed.
  • 状态消息输出到stderr,带有emoji前缀:
    (成功)、
    (错误)、
    (警告)、
    (信息)。
  • 数据输出(例如
    view --json
    )输出到stdout
  • 管道输出时,如果只需要数据输出,使用
    2>/dev/null
    抑制状态消息。

Exit codes and error recovery

退出代码与错误恢复

CodeMeaningAgent action
0SuccessProceed normally
1Generic errorRead stderr for details; may indicate commit/push failure
2Not in a stackRun
gh stack init
to create a stack first
3Rebase conflictParse stderr for conflicted file paths, resolve conflicts, run
gh stack rebase --continue
4GitHub API failureCheck
gh auth status
, retry the command
5Invalid argumentsFix the command invocation (check flags and arguments)
6Disambiguation requiredA branch belongs to multiple stacks. Run
gh stack checkout <specific-branch>
to switch to a non-shared branch first
7Rebase already in progressRun
gh stack rebase --continue
(after resolving conflicts) or
gh stack rebase --abort
to start over
8Stack is lockedAnother
gh stack
process is writing the stack file. Wait and retry — the lock times out after 5 seconds
代码含义Agent操作
0成功正常继续
1通用错误读取stderr获取详细信息;可能表示提交/推送失败
2不在堆叠中运行
gh stack init
创建堆叠
3变基冲突解析stderr中的冲突文件路径,解决冲突,运行
gh stack rebase --continue
4GitHub API失败检查
gh auth status
,重试命令
5参数无效修正命令调用(检查标志和参数)
6需要消除歧义一个分支属于多个堆叠。先运行
gh stack checkout <specific-branch>
切换到非共享分支
7变基已在进行中运行
gh stack rebase --continue
(解决冲突后)或
gh stack rebase --abort
重新开始
8堆叠已锁定另一个
gh stack
进程正在写入堆叠文件。等待并重试——锁会在5秒后超时

Known limitations

已知限制

  1. Stacks are strictly linear. Branching stacks (multiple children on a single parent) are not supported. Each branch has exactly one parent and at most one child. If you need parallel workstreams, use separate stacks.
  2. Stack disambiguation cannot be bypassed. If the current branch is the trunk of multiple stacks, commands error with code 6. Check out a non-shared branch first.
  3. Multiple remotes require
    --remote
    or config.
    If more than one remote is configured, pass
    --remote <name>
    or set
    remote.pushDefault
    in git config before running
    push
    ,
    sync
    , or
    rebase
    .
  4. Merging PRs: Merging Stacked PRs from the CLI is not supported yet. Direct users to open the PR URL in a browser to merge PRs.
  5. Remote stack checkout requires a PR number.
    checkout
    with a branch name only works with locally tracked stacks. Use a PR number (e.g.
    gh stack checkout 123
    ) to pull stacks from GitHub.
  6. PR title and body are auto-generated. There is no flag to set a custom PR title or body during
    submit
    . The title and body are generated from commit messages plus a footer. Use
    gh pr edit
    to modify PR title and body after creation.
  1. 堆叠严格线性。不支持分支堆叠(单个父分支有多个子分支)。每个分支恰好有一个父分支和最多一个子分支。如果需要并行工作流,使用单独的堆叠。
  2. 无法绕过堆叠歧义消除。如果当前分支是多个堆叠的主干,命令会以代码6错误退出。先切换到非共享分支。
  3. 多个远程仓库需要
    --remote
    或配置
    。如果配置了多个远程仓库,在运行
    push
    sync
    rebase
    之前,传递
    --remote <name>
    或在git配置中设置
    remote.pushDefault
  4. 合并PR: 目前不支持从CLI合并堆叠PR。引导用户在浏览器中打开PR URL以合并PR。
  5. 远程堆叠检出需要PR编号。使用分支名称的
    checkout
    仅适用于本地跟踪的堆叠。使用PR编号(例如
    gh stack checkout 123
    )从GitHub拉取堆叠。
  6. PR标题和正文自动生成
    submit
    期间没有标志可以设置自定义PR标题和正文。标题和正文由提交消息加上页脚生成。创建后使用
    gh pr edit
    修改PR标题和正文。