docs reference Stacks & navigation
13-stacks-and-navigation.md ReferenceJul 17, 2026

Stacks & navigation

A branch holds a stack of reviews. The commands here show that stack and move you around inside it: jump to a review or a commit, switch branches, and open linked worktrees that stay inside the GitStack model. They all read the local manifest, so run them from a checkout of a GitStack repo. The global flags --json, --plain, and --verbose work on every command below (see CLI conventions).

gs stack#

Show every review on the current branch, top of the stack first.

bash
gs stack [--commits]

Running gs with no arguments prints this same view.

Flag Description
--commits show each commit and which review covers it
Flag
--commits
Description
show each commit and which review covers it

Each row is one review. A > marks the review that HEAD sits on. The columns are the review id, its state, the title, the latest patchset (psN), and the review's most pressing metric. States read as:

State Meaning
wip has local unpushed commits, unresolved threads, or no reviewer yet
review pushed and waiting on a reviewer
ready has at least one LGTM and can land
merged landed on the base branch
abandoned closed without landing
unknown a signal could not be fetched, so the state is undetermined
State
wip
Meaning
has local unpushed commits, unresolved threads, or no reviewer yet
State
review
Meaning
pushed and waiting on a reviewer
State
ready
Meaning
has at least one LGTM and can land
State
merged
Meaning
landed on the base branch
State
abandoned
Meaning
closed without landing
State
unknown
Meaning
a signal could not be fetched, so the state is undetermined

The metric column shows the open thread count when threads are waiting for a reply, otherwise the LGTM count. Threads win, because they need your attention first. The final line is a next: hint: gs push when the branch has unpushed work, or gs submit rN when a ready review can land.

The counts come from the server with the stack itself. If the server does not report one (an older server, or a review it could not read), the review's state reads unknown and a warning line names the review and the missing signal. The metric column shows ? in place of the missing count, unless a checks state is already occupying that column, since checks take priority there. A ? never means zero: it means gs was not told, so it will not claim a state it cannot verify, and it withholds the gs submit hint for any batch that would include the affected review. Re-running gs stack retries the fetch; if the server predates stack-signal support the counts stay unknown until it is upgraded. With --json, an unknown count is null rather than a number and the same warnings are listed in a top-level warnings array.

bash
$ gs stack
> R3  ready   billing: POST /api/billing endpoint  ps2  LGTM 1
  R2  review  billing: subscription store          ps1
  R1  merged  billing: subscription model          ps1
next: gs submit R3

Review ids print in uppercase (R3), but you can type them in either case wherever a command takes one (r3 and R3 are the same review). Ids are global and never renumber, so copy them from this view rather than guessing. See Reference syntax for the full ref grammar.

gs stack --commits#

The commit-centric view. It lists commits instead of reviews and draws which review covers each one.

bash
gs stack --commits

Commits are numbered c1 through cN oldest-first, so c1 is the oldest commit above the base and the numbers stay stable as you read down. Bracket art groups the commits that belong to each review, an @ marks the commit HEAD points at, and the base branch sits on the ═══ row at the bottom. Commits that no review covers are labelled uncovered.

bash
$ gs stack --commits
  @ c3  a1b2c3d  billing: POST /api/billing  ──  R3  [ready]   billing: POST endpoint
    c2  d4e5f6a  billing: subscription store ──  R2  [review]  billing: store
    c1  9f8e7d6  billing: subscription model ──  R1  [merged]  billing: model

  ═══ main  0011223  origin/main

Use this view to carve commits into reviews bottom-up. The cN labels are the endpoints you pass to gs review create and gs checkout.

gs stack describe#

Set a description for the whole stack on the current branch.

bash
gs stack describe [-m "text"] [--clear]
Flag Description
-m, --message description text; opens $EDITOR when omitted
--clear remove the stack description
--repo repo name (default: infer from origin)
Flag
-m, --message
Description
description text; opens $EDITOR when omitted
Flag
--clear
Description
remove the stack description
Flag
--repo
Description
repo name (default: infer from origin)

With no -m, the command opens your editor prefilled with the current description so you revise it rather than overwrite it. The text is Markdown. The description is stack-level state keyed by branch, not part of any single review, so carving, split, fold, and reorder never lose it. It shows at the top of gs stack.

bash
gs stack describe -m "Adds the billing subscription flow end to end."
Non-interactive use

Outside a terminal (a script, CI), gs stack describe requires -m because there is no editor to open. --clear cannot be combined with -m.

gs stack automerge#

Turn automerge on or off for the stack on the current branch, or show whether it is on.

bash
gs stack automerge [on|off]
Flag Description
--repo repo name (default: infer from origin)
Flag
--repo
Description
repo name (default: infer from origin)

With automerge on, the server lands the whole stack, all at once, as soon as every review is approved and CI is green. It follows the repo's landing policy without the owner bypass, so the LGTMs the policy asks for are always required. The setting belongs to the stack, not to a single review.

Automerge turns on once the server has the whole stack. If you have carved or amended reviews you have not pushed yet, on waits and takes effect at your next gs push, so the server never lands the reviews it has before the rest arrive. off takes effect at once.

You can also turn it on when you carve a review, with --automerge on gs review create or gs commit --review:

bash
gs review create -t "billing: settings UI" --automerge
# created R4 (position 4)
# R1 patchset 1 (initial) ...
# automerge on: the stack lands once every review is approved and CI is green

While automerge is on, gs stack prints automerge on under the reviews.

gs checkout#

Move to a review, a commit, or a branch.

bash
gs checkout [--branch] <ref>
Flag Description
--branch force a branch checkout when the name also looks like a review or commit
Flag
--branch
Description
force a branch checkout when the name also looks like a review or commit

The ref can be a review id (R3, or R3~1 for one commit before its tip), a commit number (c2), a commit sha or any git ref, or a branch name. A review or commit ref detaches HEAD at that point so you can read or build on it; a branch name switches to the branch. When you detach, gs records the branch you left in .gitstack/last-branch, so gs top can re-attach you afterward. gs checkout top does that re-attach directly.

bash
gs checkout r2        # detach at review r2's tip to inspect it
gs checkout main      # switch back to the main branch
Stack-shaped names never create a branch

A name like R5 or c9 that does not resolve to a real review or commit is refused rather than silently creating a branch called R5, which is almost always a mistyped ref. If you genuinely want a branch with that name, pass --branch.

gs switch#

Switch to another branch.

bash
gs switch [-c] <branch>
Flag Description
-c create the branch and switch to it
Flag
-c
Description
create the branch and switch to it
bash
gs switch -c add-billing   # start a new branch
gs switch main             # go back to an existing branch

gs top#

Return to the top of the stack.

bash
gs top [--discard]
Flag Description
--discard discard tracked changes first
Flag
--discard
Description
discard tracked changes first

After a gs checkout rN or gs checkout cN leaves you on a detached HEAD, gs top re-attaches you to the branch recorded in .gitstack/last-branch and puts HEAD back at the tip. It refuses when the worktree has uncommitted changes to tracked files, unless you pass --discard to reset them first. New untracked files (including gs bookkeeping under .gitstack/) do not count as dirty.

bash
gs checkout r2   # detach to look at an earlier review
gs top           # jump back to the tip of the branch

gs branch#

List branches with their GitStack review state. Local branches by default.

bash
gs branch [-r | -a] [--remote origin]
Flag Description
-r, --remotes list remote-tracking branches instead of local ones
-a, --all list local branches, then remote-tracking branches
--remote remote a local branch without an upstream is compared against (default: origin)
Flag
-r, --remotes
Description
list remote-tracking branches instead of local ones
Flag
-a, --all
Description
list local branches, then remote-tracking branches
Flag
--remote
Description
remote a local branch without an upstream is compared against (default: origin)

A * marks the current branch. The state column shows the review count when a branch has reviews (3 reviews), otherwise the branch's sync state against its upstream: synced, ahead N, behind N, diverged +N/-M, or no upstream.

bash
$ gs branch
* add-billing   3 reviews  a1b2c3d  billing: POST /api/billing
  main          synced     0011223  chore: bump deps
  fix-login     ahead 2    7788990  login: retry on 401

Remote-tracking branches come from your last fetch, so run gs fetch first to see what is on the server now. Their state column shows the review count when gs has the branch's stack, otherwise remote.

bash
$ gs branch -r
  origin/add-billing  3 reviews  a1b2c3d  billing: POST /api/billing
  origin/main         remote     0011223  chore: bump deps

gs worktree#

Manage linked worktrees with gs-aware branch handling. Plain git worktree add creates branches outside GitStack and git worktree remove judges safety with ancestry checks that squash-landing defeats. These subcommands keep both inside the gs model.

bash
gs worktree add <branch> [--path <dir>]
gs worktree remove <branch|path> [--force]
gs worktree list

gs worktree add#

Create a branch and a linked worktree for it in one step.

bash
gs worktree add [--path <dir>] <branch>
Flag Description
--path worktree location (default: <repo>/.worktrees/<branch>)
Flag
--path
Description
worktree location (default: <repo>/.worktrees/<branch>)

The branch is created with the same semantics as gs switch -c. By default the worktree lands at <repo>/.worktrees/<branch>, which gs adds to the repo's machine-local info/exclude so it never shows up as an untracked path. Pass --path to put it somewhere else. If the branch already exists, gs checks it out into the new worktree instead of creating it.

bash
gs worktree add reference-docs
# created worktree /repo/.worktrees/reference-docs on branch reference-docs
# next: cd /repo/.worktrees/reference-docs

gs worktree remove#

Remove a worktree and, when its work is fully landed, delete the branch too.

bash
gs worktree remove [--force] [--keep-remote] <branch|path>
Flag Description
--force remove despite uncommitted changes or unlanded commits (the branch is kept)
--keep-remote keep the remote branch even when it is safe to delete
--repo repo name (default: infer from origin)
Flag
--force
Description
remove despite uncommitted changes or unlanded commits (the branch is kept)
Flag
--keep-remote
Description
keep the remote branch even when it is safe to delete
Flag
--repo
Description
repo name (default: infer from origin)

Target the worktree by its branch name or its path. When every review on the branch has landed or been abandoned, gs also deletes the local branch and, via gs cleanup, the remote branch. Safety is judged by content using a merge-tree check, not by branch ancestry, so a squash-landed branch (whose commits have different shas than the base) still qualifies for deletion.

The command refuses when the worktree has uncommitted changes or the branch has commits whose content is not yet on the base. Pass --force to remove the worktree anyway; the branch is kept in that case. It also refuses to remove the primary checkout or the worktree you are currently sitting in.

bash
gs worktree remove reference-docs
Related cleanup

gs worktree remove composes with gs cleanup under the same server-confirmed rules. For landing reviews and reclaiming branches on their own, see Landing & cleanup.

gs worktree list#

List the repo's worktrees. This is a passthrough to git worktree list.

bash
gs worktree list
bash
$ gs worktree list
/repo                        0011223 [main]
/repo/.worktrees/add-billing a1b2c3d [add-billing]