Skip to content

A day with g2g

Every command that changes anything previews first and acts only with --apply. Run each one bare to read the plan, then add the flag. Moving the checkout is the one exception. See Preview and apply.

The branch names in the commands are placeholders. The output shown on this page is real, captured from g2g 0.38.0 without colour in a small scratch repository with a stack of auth, login and session on main.

Terminal window
g2g adopt --trunk main --apply
g2g status

You do this once. The order of the branches comes from commit ancestry, so the only thing you assert is the trunk, and it has to be named the first time because nothing recorded implies it yet. adopt records a whole stack in one step, which is almost always what a repository that predates g2g needs. See Shape the stack.

g2g status then draws the stack you are on from g2g’s own record. It asks nothing of the network, so it is the command to run before deciding whether anything else needs to happen:

Target session · current Git branch
○ main trunk
│
● auth
● login
● session ← target
Scope stack · 4 branches · /work/app/.git/g2g/graph.json

What that record is, and why it lives in the repository rather than on GitHub, is The forest. What status reports about each branch is on Status and doctor.

Terminal window
g2g github adopt --apply

With every branch of their stack fetched and checked out here, this adopts the structure their pull requests declare, so you do not have to track each branch by hand. It is the only adoption that needs the network. See GitHub.

Terminal window
g2g create synthetic-three -m "Add the third change" --apply
g2g down 2

create starts a branch on the one you stand on, switches to it, records it, and with -m commits what is staged onto it. Run without --apply, it shows the steps it would take. Here is the preview of creating login on auth with one file staged:

Target login · new branch
○ main trunk
│
● auth
● login new ← target
Commands this would run, in order
1 git switch -c login auth · start login at auth and check it out
2 g2g track --branch login --parent auth --apply · record it under auth
3 git commit -m 'Add login' · commit what is staged
Creates login at ab0c00ad2b9d, the tip of auth, and switches to it.
Records login under auth.
Commits 1 staged file (login) onto it.
Graph store · /work/app/.git/g2g/graph.json
No changes were made. Rerun with --apply to create it.

up, down, top and bottom move the checkout. They change nothing but where you stand, so they act straight away. See Move around.

Change a branch in the middle, then replay what sits on it

Section titled “Change a branch in the middle, then replay what sits on it”
Terminal window
git commit --amend
g2g restack --apply
g2g top

Amending auth leaves login and session built on the commit it used to be. g2g restack replays them onto the new one. By default it takes the branch you stand on and everything above it, so a conflict further down that you are deliberately putting off stays put off. See Scope.

The preview says in advance whether the replay applies cleanly:

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.

A clean replay never touches your working tree or checked-out branch. When it cannot apply cleanly, the preview says so before you apply, and the rebase then happens in your own working tree so you can resolve the conflict with your own tools. See Restack, pull, prune.

g2g top then follows the branch above until there is none:

Switched to session · top of the stack from auth
Terminal window
g2g fold --apply
g2g delete --branch synthetic-abandoned --apply
g2g restack --apply
g2g rename synthetic-better-name --apply
  • fold merges a branch into the one below it: the parent fast-forwards to the branch, and the branch goes.
  • delete removes a branch and records what sat on it on what it sat on. The restack that follows replays those children onto their new parent, which drops the deleted branch’s commits from them.
  • rename gives a branch a new name and rewrites every record of it.

None of them replays a commit themselves; that stays restack’s job. See Shape the stack.

Terminal window
g2g pull --prune --apply

This fetches, fast-forwards the trunk, replays the stack onto it, and then forgets the branches whose work has landed. It is git switch main && git pull && git switch back && restack in one command, plus the prune you usually want after a squash merge upstream. See Restack, pull, prune.

Terminal window
g2g push --apply
g2g submit --edit --apply # also keeps the stack comments; --no-comment skips
g2g github retarget --apply
g2g github comment --apply # or keep them by hand, any time
g2g github status
  • push publishes the branches in one atomic, lease-protected push.
  • submit opens missing pull requests as drafts and keeps a stack comment on each one. --edit opens one document in $EDITOR for every title and body.
  • github retarget fixes pull request bases a restack left stale, so each one merges into the right branch.
  • github comment keeps the stack comments, and can be run on its own at any time.
  • github status checks it all against GitHub.

See Push and submit and GitHub.

Terminal window
g2g doctor

doctor reads every recorded stack, offline, and lists only what needs putting right, each with the command that does it. When there is nothing, it says so:

Target every recorded stack · repository
Nothing needs putting right across 3 recorded branches.

It exits 1 when it finds something, so a script can ask. See Status and doctor.

Terminal window
g2g land
g2g land --apply

From the top of the stack, land merges it down onto the trunk, bottom branch first. The preview is the list of commands it would run, in order, so you can also drive it by hand. See Land.