Reference syntax
Most gs commands take a short token that names a review, a commit, a range of
commits, or a comment thread. This page lists every form, what it resolves to,
and which commands accept it. Copy ids from gs stack, gs review list, and
gs review comments rather than counting positions in the stack. Where a form
is thin in --help, the behavior below comes from the source.
Review references (rN)#
A review id is rN, for example r48. The server allocates it, and it is
global to the repo. It is not a position in your stack, so r48 stays r48
even as you add reviews below it or land the ones above it. Read the id from
gs stack or gs review list; do not guess it.
Case does not matter. r48 and R48 are the same review. gs prints the
capital-R form.
| Command | What the review id names |
|---|---|
gs checkout rN |
detach at the review's tip |
gs review show / diff / comments / approve rN |
the review to read (defaults to the review at HEAD when omitted) |
gs review reply / resolve rN <thread> |
the review that owns the thread |
gs review split rN --at <ref> |
the review to split |
gs checkout rNgs review show / diff / comments / approve rNgs review reply / resolve rN <thread>gs review split rN --at <ref>gs checkout also accepts an rN~k suffix, meaning k commits before the
review's tip. r48~1 is the commit one below r48's tip. This suffix is for
navigation only. The review subcommands (show, diff, comments, approve, reply,
resolve, split) take a bare rN and reject a ~ suffix.
A name shaped like rN, cN, or their uppercase forms that fails to resolve
is treated as a mistyped stack ref, not a request for a new branch.
gs checkout r65 refuses rather than creating a branch called r65. Pass
--branch if you really do mean a branch with that name.
Commit references (cN)#
A commit reference is cN, for example c3. It counts commits on the current
branch oldest-first, starting from the merge-base with the default branch. c1
is the oldest commit on the branch. The numbers match what
gs stack --commits prints, so you can reference what you see on screen.
cNcounts every commit on the branch above the merge-base, whether or not a review already covers it. It is not limited to uncovered commits.- The
cmust be lowercase.C3is not a commit reference. - A number past the newest commit is an error.
cN is accepted as a range endpoint in gs review create, as the --at
anchor in gs review split, and as a checkout target in gs checkout.
Commit ranges for review create#
gs review create [range] reads a single positional argument and decides which
commits the new review covers. The forms:
| Argument | Commits covered |
|---|---|
| omitted | every uncovered commit above the topmost review (that review's tip up to HEAD, or the merge-base with the default branch up to HEAD for the first review) |
A..B |
commits after A, up to and including B (standard git revspec) |
c3 (bare endpoint) |
just that one commit, from its parent up to it |
a SHA or HEAD~1 (bare endpoint) |
just that one commit |
A..Bc3 (bare endpoint)HEAD~1 (bare endpoint)Endpoints resolve the same way on both sides of a range. cN indexes the
branch as described above; anything else (a SHA, HEAD~2, a tag) is handed to
git rev-parse.
Contiguity#
Reviews on a branch tile the commits with no gaps and no overlap. The left side of your range (A, or the parent of a bare endpoint) has to equal the previous review's tip, or the merge-base with the default branch when this is the first review. If it does not, gs stops before posting:
gs review create: range base <sha> != previous review tip <sha>When the commits already sit inside another review, gs names that review and
points you at gs review split instead.
gs review create c3 carves only c3. To cover everything
from c3 up to the branch tip, write the range out: gs review create c3..HEAD.
--last N#
--last N is a guard, not a selector. It resolves to the default uncovered
range, then checks that the uncovered region holds exactly N commits. If the
count differs, gs errors:
--last N must match the uncovered commit countUse it in scripts to assert "carve exactly the N commits I just made" and fail
loudly if the tree drifted underneath you. --last and a range expression
cannot be combined.
gs review create # all uncovered commits above the top review
gs review create c2..c4 -t "..." # commits after c2 through c4
gs review create c5 -t "..." # only c5
gs review create --last 1 -t "..." # the single uncovered commit, or an error
Split anchors (review split --at)#
gs review split rN --at <ref> divides one review in two. --at takes a single
endpoint and resolves it exactly like a range endpoint: cN, a SHA, or a git
revision such as HEAD~2. The anchor becomes the boundary between the original
review and a new review stacked above it; -t names that new upper review, and
its top commit's subject is the default. See reviews for the
full mechanics.
gs review split r48 --at c3
gs review split r48 --at HEAD~1 -t "extract the retry loop"
Thread references#
Every comment thread has a unique id, a ULID. gs review comments prints the
shortest prefix that identifies each thread on that review, at least four
characters long. You reference a thread by that prefix.
| Command | Thread argument |
|---|---|
gs review reply rN <thread> |
the thread to reply to |
gs review resolve rN <thread> |
the thread to resolve |
gs commit --resolves <thread> |
mark resolved on next push (repeatable) |
gs amend --resolves <thread> |
mark resolved on next push (repeatable) |
gs review reply rN <thread>gs review resolve rN <thread>gs commit --resolves <thread>gs amend --resolves <thread>- Matching is by prefix and case-insensitive. Paste the short prefix gs showed you, a longer prefix, or the full ULID.
- A prefix that matches more than one thread on the review is an "ambiguous thread prefix" error. A prefix that matches none is "unknown thread prefix".
--resolvesis resolved against the review at HEAD, the one your commit or amend lands in, and takes effect on the nextgs push. It is repeatable, so pass it once per thread.
gs review comments r48 --unresolved
gs amend --no-edit --resolves 01H8 --resolves 01J2
gs push
gs review reply r48 01H8 -m "done"
Stack and git refs#
gs checkout accepts a few targets beyond reviews and commits:
| Ref | Meaning |
|---|---|
top |
re-attach HEAD to the branch you left (same as gs top) |
| a branch name | switch to any local or origin branch |
| a SHA or git revision | detach at any commit git can resolve (HEAD~2, a tag, a short SHA) |
topgs top)HEAD~2, a tag, a short SHA)Reference quick lookup#
| Form | Example | Accepted by |
|---|---|---|
review id rN |
r48 |
gs checkout; gs review show / diff / comments / approve / reply / resolve / split |
review tip offset rN~k |
r48~1 |
gs checkout only |
commit cN |
c3 |
gs review create endpoint; gs review split --at; gs checkout |
range A..B |
c2..c4 |
gs review create (one endpoint feeds split --at) |
| bare endpoint | c5, HEAD~1, a SHA |
gs review create (one commit); gs review split --at |
guard --last N |
--last 1 |
gs review create |
| thread prefix | 01H8 |
gs review reply / resolve; gs commit / amend --resolves |
top |
top |
gs checkout |
| branch or SHA | main, HEAD~2 |
gs checkout |
rNr48gs checkout; gs review show / diff / comments / approve / reply / resolve / splitrN~kr48~1gs checkout onlycNc3gs review create endpoint; gs review split --at; gs checkoutA..Bc2..c4gs review create (one endpoint feeds split --at)c5, HEAD~1, a SHAgs review create (one commit); gs review split --at--last N--last 1gs review create01H8gs review reply / resolve; gs commit / amend --resolvestoptopgs checkoutmain, HEAD~2gs checkoutFor the commands that consume these forms, see commits and syncing, stacks and navigation, and reviews.