Skip to content

Stacked commits

garden has no local branches. You work as a stack of commits, and each commit becomes its own pull request.

If you’ve used Gerrit or Phabricator, this is that model. Coming from GitHub, the shift is: one commit = one PR, instead of one branch = one PR.

Commits build on each other. garden stack (alias smartlog, sl) draws them as a graph annotated with each one’s PR status.

Bookmarks replace branches, and garden branch manages bookmarks. You rarely need them — your position in the stack is what matters, and garden prev / garden next move through it.

Terminal window
garden push

push pushes the current commit and all its draft ancestors, bottom-up, opening or updating one PR per commit. Each is diffed against its parent, so a reviewer sees one logical change rather than a 900-line branch.

There is no garden pr create — running it points you back at push. Title and body come from the commit message.

The habit that differs most from GitHub:

Terminal window
# edit the files
garden commit --amend
garden push

garden finds the existing PR via the predecessor commit and adds a new revision. Review threads from earlier revisions carry over.

Adding a “fix review comments” commit on top would open a new PR for the fixup, which is almost never what you want.

Command What it does
garden absorb Amends pending changes into whichever commits they belong to
garden split Splits one commit into several
garden fold (squash) Combines several commits into one
garden uncommit Undoes the last commit, keeping its changes pending
garden restack Rebases orphaned descendants onto their rewritten parents

garden absorb is the one to learn first: after fixing three review comments across three files, it routes each hunk to the right commit without you naming any of them.

If fold or split rewrites commits with open PRs, garden warns you — the PRs follow the rewrite, and a folded pair means one closes.

Terminal window
garden pull

There is no fetch and no remote: there is one canonical server. pull fetches trunk and rebases your stack onto it, dropping commits that already landed. --no-rebase gives you a plain fetch.

Each commit is its own PR, and a child’s diff is defined against its parent, so the merge queue lands them in order.