docs reference Commits & syncing
12-commits-and-syncing.md ReferenceJul 17, 2026

Commits & syncing

This is the loop you run all day. Stage a change, commit it into a review, push the branch, and sync when the base branch moves under you. GitStack keeps the whole stack on one branch, so a commit lands inside a review and a push updates the branch and its manifest together. When gs rewrites history it tells you which reviews changed and how.

Every command here also takes the global flags (--plain, --json, --verbose); see CLI conventions. Review ids and thread ids follow the forms in reference syntax.

gs add#

Stage files. This is a passthrough to git add.

gs commit does not stage for you. Run gs add first, or pass -a to commit to stage tracked modifications.

bash
gs add <pathspec>...

gs add takes the same pathspecs as git add and has no flags of its own.

bash
gs add internal/billing/model.go internal/api/billing.go

gs commit#

Create a commit. It extends the topmost review, or inserts into a lower review when HEAD sits there.

bash
gs commit -m "message"
gs commit -m "message" --review -t "title"
Flag Description
--message, -m commit message
--all, -a stage tracked modifications before committing
--review after committing, carve a new single-commit review
--title, -t title for the new review (with --review)
--fixes N issue this stack fixes, repeatable, requires --review
--automerge land the whole stack once every review is approved and CI is green, requires --review
--resolves <id> thread id or prefix to mark resolved on the next push, repeatable
--amend alias for gs amend
--no-edit reuse the prior message (with --amend)
--continue resume after a rebase conflict
--abort discard the in-flight commit
--allow-dirty with --review, push even when the tree has other uncommitted or untracked changes
--squash land this review as one commit (the default)
--rebase land this review's commits as they are, on top of the base
Flag
--message, -m
Description
commit message
Flag
--all, -a
Description
stage tracked modifications before committing
Flag
--review
Description
after committing, carve a new single-commit review
Flag
--title, -t
Description
title for the new review (with --review)
Flag
--fixes N
Description
issue this stack fixes, repeatable, requires --review
Flag
--automerge
Description
land the whole stack once every review is approved and CI is green, requires --review
Flag
--resolves <id>
Description
thread id or prefix to mark resolved on the next push, repeatable
Flag
--amend
Description
alias for gs amend
Flag
--no-edit
Description
reuse the prior message (with --amend)
Flag
--continue
Description
resume after a rebase conflict
Flag
--abort
Description
discard the in-flight commit
Flag
--allow-dirty
Description
with --review, push even when the tree has other uncommitted or untracked changes
Flag
--squash
Description
land this review as one commit (the default)
Flag
--rebase
Description
land this review's commits as they are, on top of the base

At the top of the stack, the commit extends the topmost review and prints a short hint naming the review it joined. Mid-stack (HEAD checked out at a lower review), the commit inserts into that review. That review classifies as extended, and every review above it rebases automatically. Extending a review resets its LGTMs, because the reviewer has new code to look at. Reviews that only rebase keep their approvals. See reviews for how approvals work.

--review -t carves in one step. It commits, carves the new commit into a fresh single-commit review at the top of the stack, and pushes so the server allocates patchset 1. It only works at the top. If the tree still carries other uncommitted changes, the carve keeps the review but skips that final push (partial staging is supported) and leaves a next: gs push hint. Pass --allow-dirty to push anyway and leave those changes local.

--resolves takes a thread id or a unique prefix and is repeatable. The threads are marked resolved when the commit reaches the server on the next push.

The --squash and --rebase flags declare how the carved review lands later. See landing and cleanup.

bash
gs add internal/billing/webhook.go
gs commit -m "billing: handle Stripe webhook" --review -t "billing: webhook handler"

A mid-stack insert can hit a conflict while the reviews above rebase. The commit pauses. Resolve the files, gs add them, then gs commit --continue. Use gs commit --abort to discard the in-flight commit and restore the stack.

--review is top-only

gs commit --review carves the top commit into a new review, so it only works at the top of the stack. For mid-stack reshaping use gs review create or gs review split. See reviews.

gs amend#

Amend HEAD's commit. It stays put at the top of the stack and rebases downstream when mid-stack.

bash
gs amend
gs amend --no-edit
Flag Description
--message, -m new commit message
--no-edit reuse the prior commit message
--resolves <id> thread id or prefix to mark resolved on the next push, repeatable
--continue resume after a rebase conflict
--abort discard the in-flight amend
Flag
--message, -m
Description
new commit message
Flag
--no-edit
Description
reuse the prior commit message
Flag
--resolves <id>
Description
thread id or prefix to mark resolved on the next push, repeatable
Flag
--continue
Description
resume after a rebase conflict
Flag
--abort
Description
discard the in-flight amend

gs amend rewrites the commit at HEAD. The review it belongs to classifies as revised, so its LGTMs reset. At the top of the stack nothing above needs to move. Mid-stack, gs amend rebases every review above the one you changed, and those rebased reviews keep their approvals.

--no-edit keeps the existing message. --resolves marks threads resolved on the next push, the same as on gs commit.

bash
gs checkout r1
gs add internal/billing/model.go
gs amend --no-edit --resolves 01H8
gs push

A conflict during the downstream rebase pauses the amend. Resolve, gs add the files, then gs amend --continue (or gs amend --abort to discard it).

Amending resets that review's LGTMs

A revised review needs a fresh sign-off. The reviews above keep their approvals, because they were replayed onto your new commit, not rewritten.

gs push#

Push the branch and its manifest in one atomic update.

bash
gs push
Flag Description
--force force-with-lease the branch (rarely needed)
--allow-dirty push even when the tree has uncommitted or untracked changes
Flag
--force
Description
force-with-lease the branch (rarely needed)
Flag
--allow-dirty
Description
push even when the tree has uncommitted or untracked changes

A single push updates the branch ref and the manifest ref together, and the server classifies each patchset in the same transaction. The push is atomic: if the server refuses the branch update (another clone pushed first), it refuses the manifest too, so the server never holds a manifest for a branch tip it does not have. Run gs sync and push again. After a rewrite that gs performed (a mid-stack commit, an amend, or a sync rebase) gs arms the lease and pushes with --force-with-lease for you. Do not pass a manual --force. The flag exists for rare recovery and is usually redundant.

gs push refuses when the working tree has uncommitted or untracked changes, because a push only sends commits and a forgotten gs commit is the usual cause. When those changes are meant to stay local (scratch files, a build artifact, an edit you are not ready to commit), pass --allow-dirty. The commits push and the rest stays in your working tree. gs review create, gs review split, gs review fold, and gs commit --review take the same flag for the push they make.

gs push prints one line per changed review:

r1 patchset 3 (revised) gp_a1b2
r2 patchset 2 (rebased) gp_c3d4
resolved thread 01H8

The kinds map to what happened to the review. extended means new commits fast-forwarded onto it, revised means its commit was rewritten, and rebased means it was replayed onto a moved base with no content change. Any threads you marked with --resolves print their own outcome line, and a warning prints when the server could not resolve one.

"local manifest diverged from server"

If push refuses with this message, another clone pushed since you last synced. Run gs sync to reconcile, then push again.

gs sync#

Reconcile the local manifest with the server, then rebase onto a moved base.

bash
gs sync
gs sync --manifest-only
Flag Description
--manifest-only reconcile the manifest only, never rebase the stack
--discard-local-edits adopt the server's stack even when that drops a split, fold, or reorder you have not pushed
--continue resume a sync paused on a rebase conflict
--abort discard a paused sync and restore the stack
Flag
--manifest-only
Description
reconcile the manifest only, never rebase the stack
Flag
--discard-local-edits
Description
adopt the server's stack even when that drops a split, fold, or reorder you have not pushed
Flag
--continue
Description
resume a sync paused on a rebase conflict
Flag
--abort
Description
discard a paused sync and restore the stack

gs sync pulls the server's authoritative manifest and replaces the local copy when they differ. When the base branch has moved past your stack, sync rebases the whole stack onto the new base and pushes it, printing a line like:

rebased r1 r2 onto main

A split, fold, or reorder you have not pushed yet (one made with --no-push, or whose push failed) is kept: sync rebases the stack with it and pushes it. If the server's stack also changed since your last push, sync cannot carry the edit over safely, so it refuses and names it. Run gs sync --discard-local-edits to take the server's stack instead, then redo the edit.

Sync is idempotent, so running it again on a current stack does nothing. With --manifest-only it reconciles the manifest and never rebases or touches the working tree, which is the safe form to run when you only want the latest review state.

A conflict during the rebase pauses sync. Resolve the files, gs add them, then gs sync --continue. Use gs sync --abort to drop the paused sync and restore the stack to where it started.

Sync rebases the whole stack

A dirty working tree blocks the rebase. Commit or stash your changes first, then run gs sync again.

gs status#

Show working-tree state and where HEAD sits in the stack. It is local only and makes no server calls.

bash
gs status
gs status --remote
Flag Description
--remote also show remote branch diagnostics
Flag
--remote
Description
also show remote branch diagnostics

gs status prints a single line: the branch, the review HEAD sits in out of the total, and whether the tree is clean or how many files changed.

on add-billing · r2 of 3 · 2 changed

When the repo is in a recovery state, a paused rebase or HEAD parked off the stack, a banner prints above that line with the command to get unstuck. Pass -v to expand the changed-file detail. --remote adds remote diagnostics: where this worktree fetches and pushes, and whether the branch exists on the server yet.

For moving HEAD around the stack that gs status reports on, see stacks and navigation.