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.
gs stack [--commits]
Running gs with no arguments prints this same view.
| Flag | Description |
|---|---|
--commits |
show each commit and which review covers it |
--commitsEach 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 |
wipreviewreadymergedabandonedunknownThe 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.
$ 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.
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.
$ 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.
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) |
-m, --message$EDITOR when omitted--clear--repoWith 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.
gs stack describe -m "Adds the billing subscription flow end to end."
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.
gs stack automerge [on|off]
| Flag | Description |
|---|---|
--repo |
repo name (default: infer from origin) |
--repoWith 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:
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.
gs checkout [--branch] <ref>
| Flag | Description |
|---|---|
--branch |
force a branch checkout when the name also looks like a review or commit |
--branchThe 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.
gs checkout r2 # detach at review r2's tip to inspect it
gs checkout main # switch back to the main 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.
gs switch [-c] <branch>
| Flag | Description |
|---|---|
-c |
create the branch and switch to it |
-cgs 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.
gs top [--discard]
| Flag | Description |
|---|---|
--discard |
discard tracked changes first |
--discardAfter 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.
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.
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) |
-r, --remotes-a, --all--remoteorigin)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.
$ 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.
$ 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.
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.
gs worktree add [--path <dir>] <branch>
| Flag | Description |
|---|---|
--path |
worktree location (default: <repo>/.worktrees/<branch>) |
--path<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.
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.
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) |
--force--keep-remote--repoTarget 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.
gs worktree remove reference-docs
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.
gs worktree list
$ gs worktree list
/repo 0011223 [main]
/repo/.worktrees/add-billing a1b2c3d [add-billing]