Skip to content

Preview and apply

All mutating commands preview first and require --apply. Run a command bare and it describes what it would do, then ends by saying nothing changed:

Target auth · current Git branch
● auth ← target
● login needs restack
● session
Replays login and session onto auth.
Applies without touching your working tree or checked-out branch.
No changes were made. Rerun with --apply to replay these commits.

Nothing is written to g2g’s record without an explicit --apply either. Observing a pull request base or inferring an ancestry edge produces a preview, never a record.

With --apply a command does not trust the preview you read. It re-discovers the state and revalidates it against the preview before mutating, renders and flushes the final plan first, and refuses ambiguous or unsafe work instead of guessing. On success it prints a concise confirmation:

Ready to apply
Target auth · current Git branch
● auth ← target
● login needs restack
● session
Replays login and session onto auth.
Applies without touching your working tree or checked-out branch.
Replayed.
Branch contents now match the recorded structure.
Suggested next step: g2g push

On failure it never claims that changes were made.

Where a preview includes a command for you to run by hand, such as the gh stack link command github link shows, copying it is a separate, deliberate snapshot. Running it yourself does not make g2g re-resolve anything.

up, down, top and bottom act without --apply, deliberately. Moving the checkout changes no ref, record or remote, and git switch already refuses to overwrite a local change, so a preview would only be a second command to type. --dry-run says where they would go, and the git switch that gets there, without moving. See Move around.

restack is g2g’s only resumable operation. When it stops on a conflict, you resolve it and run g2g restack --continue, or g2g restack --abort to put everything back. Until then, every other command that changes anything refuses: mid-restack a branch may already have moved while the record still says where it used to be. See Restack, pull, prune.

Interactive confirmation, or a cancellation or cooldown period before a mutation, is intentionally deferred. It needs a separate safety design and is not implied by the current --apply flow.

Status Meaning
0 it did what was asked, or there was nothing to do
1 doctor only: it found something that needs putting right
2 it failed, and achieved nothing
3 it did part of what was asked and stopped somewhere you have to act

A command exits 3 when it did some of its work and then stopped:

  • pull stopping on a conflict mid-replay;
  • pull --prune whose prune refused after the pull had happened;
  • land stopping part-way down a stack after something merged;
  • github comment stopping after writing some of its comments;
  • create -m whose commit failed after the branch was recorded;
  • a delete, fold or rename that could not put back what it had done.

A descent that stopped before changing anything is an ordinary failure.

These are not failures to retry, because what replayed stays replayed and what merged stays merged. They are not successes either. Both print what happened and what to do next; the status lets something reading only the status tell the difference, the way git rebase and git merge exit non-zero when they stop needing you.

doctor’s 1 follows diff and grep: a script asking whether anything is wrong wants the answer as a status, and 2 stays “could not tell”. See Status and doctor.