Stacked changes¶
A stack is a chain of feature branches where each one builds on the one below it instead of on the trunk. You split a large change into reviewable pieces, keep working on top of code that hasn't merged yet, and let git-city keep the whole tower consistent for you.
git-city makes stacks first-class. Every feature records its parent in Git config, so a stack is just a path down the branch tree rooted at your trunk. You don't track that relationship by hand — new --onto writes it, tree shows it, sync --all respects it, and land repairs it.
Note
If the parent/trunk idea is new to you, read the mental model first. The short version: a trunk is long-lived and never rebased; a feature is everything you work on and it knows its parent. A stack is several features parented onto each other.
Build the stack¶
Start the bottom branch off the trunk, then stack each new branch onto the previous one with --onto.
git city new api creates api off the trunk (main), records main as its parent, and checks it out. git city new ui --onto api then creates ui, records api as its parent, and checks ui out. You now have a two-deep stack: main → api → ui.
| Command | What it does |
|---|---|
git city new <name> |
Branch off the trunk; parent is the trunk. |
git city new <name> --onto <branch> |
Stack <name> onto <branch>; parent is <branch>. |
Tip
new moves commits, so it refuses to run on a dirty working tree — commit or stash first. Add --dry-run to any command on this page to print the exact git commands it would run without executing anything.
→ new
See the shape¶
git city tree prints the hierarchy as an indented tree. The current branch is marked with a filled dot, and each feature shows how far ahead/behind it is versus its parent.
Here api has 3 commits on top of main, and ui has 2 commits on top of api. The ● shows you're currently on ui. The tree is read-only — it never touches your branches.
→ tree
Sync the whole stack¶
When the trunk moves on, the whole stack needs to be rebased back on top of it — and each branch needs to be rebased on top of its (now-updated) parent, in order. git city sync --all does exactly that: it syncs every feature parents before children (topological order), updating each trunk once.
For each feature this fetches, brings the parent up to date (recursively), rebases the feature onto its parent — first absorbing any commits the remote has that you don't — and force-pushes with --force-with-lease. Doing it parent-first means api is settled before ui rebases onto it, so the stack stays coherent from the bottom up.
Warning
A rebase can hit a conflict. sync is resumable: it pauses, leaves the rebase in progress, and tells you what to do. Resolve the conflict, git add, then git city continue — or git city abort to roll the whole thing back to where it started.
You can also sync a single branch by name (git city sync api); without --all only that branch and its ancestors are brought up to date.
Land the bottom branch¶
When the bottom of the stack is ready to merge, land it. git city land fast-forwards the parent to the feature's tip (history stays linear), re-homes the feature's children onto the parent, and pushes the parent. It keeps the landed feature (tagged landed) so you can keep working on it; prune removes landed branches later, or land --delete removes it immediately.
Re-homing is the part that keeps a stack alive: when you land api into main, ui's parent is automatically changed from api to main. The next sync rebases ui cleanly onto the trunk.
After landing api, the tree collapses by one level:
Note
land refuses if the feature is behind its parent — run git city sync first so the fast-forward is possible. Land the stack from the bottom up: land api, then once ui is reviewed, land ui.
→ land
The whole loop¶
git city new api # bottom of the stack, off main
git city new ui --onto api # stacked on api
git city tree # check the shape
git city sync --all # rebase the whole stack on the latest trunk
git city land api # merge the bottom; ui re-homes onto main
That's the full stacked workflow: branch, stack, view, sync, land — with git-city tracking parents, ordering the rebases, and repairing the tree so you never hand-edit the lineage.