Skip to content

land (merge) & prune

git city land finishes a feature: it fast-forwards the parent to the feature's tip, re-homes the feature's children onto that parent, and pushes the parent. Because the parent fast-forwards, your history stays perfectly linear — there is no merge commit and no rebase to redo. By default it keeps the feature branch (flagged landed) so you can keep working on it; prune sweeps landed branches away later, or land --delete removes it on the spot.

git city merge is an exact alias; use whichever verb reads better to you.

git city land [branch] [--delete] [--yes] [--dry-run]

With no branch, git-city lands the current branch. Land moves commits, so it refuses to run on a dirty working tree — commit or stash first. Plain land keeps the branch and is fully reversible, so it does not prompt; land --delete deletes the feature locally and on the remote, so it prints the plan and asks for confirmation (pass --yes / -y to skip it, required to run non-interactively).


Why it keeps the branch

Deleting the branch the instant you land is a footgun: think you're done, land, then spot a bug — and the branch you wanted to fix is gone. So land keeps it. If you find a problem afterwards, switch back, commit the fix, and land again. When you're genuinely finished, prune removes every branch you've landed in one go.

A kept branch sits at its parent's tip (ahead 0) carrying a landed flag, shown as a landed tag in info and tree. Commit to it again and it is ahead of the parent once more — no longer "merged" — so prune leaves it alone until you re-land.


What it does

For a feature whose parent is up to date, land performs these steps in order:

  1. Fast-forward the parent to the feature's tip. The feature's commits become part of the parent with no merge commit (linear history).
  2. Re-home the children. Any branches stacked on the feature are reparented onto the parent, so the rest of the stack stays intact. The commits do not move now — the next sync restacks each child onto the updated parent.
  3. Push the parent to its remote.
  4. Flag the feature landed and keep it — or, with --delete, delete it both locally and on the remote.
Argument / option Meaning
branch The feature to land. Defaults to the current branch.
--delete / -d Delete the feature (local + remote) instead of keeping it, as land did before.
--yes / -y Skip the confirmation prompt for --delete (and allow non-interactive use).
--dry-run Print the exact ordered git commands and execute nothing.

Note

The alias git city merge exists for muscle memory, but land never creates a merge commit. The parent simply fast-forwards over the feature's commits.


Must be synced first

Land refuses if the feature is behind its parent — that is, the parent has commits the feature does not. A fast-forward is only possible when the feature's tip already contains the parent's tip, so you must rebase first:

git city sync
git city land

After a clean sync the feature sits directly on top of its parent, the fast-forward is trivially possible, and land proceeds.

Tip

Run git city (the dashboard) or git city tree before landing. If the feature shows ↓ (behind) against its parent, sync before you land.

→ sync


Example

You have a feature add-login on main, fully synced:

main  (trunk)
└─ ● add-login  ↑2 ↓0

Preview exactly what will run:

git city land --dry-run

Then land it:

git city land

add-login's two commits are now on main, main is pushed, and add-login is kept — sitting at main's tip with a landed tag, ready for you to keep working on if you need to. If add-login had children, each one is now parented on main and will restack onto it on its next sync. When you're done, remove it (and any other landed branches) with:

git city prune

Or land and delete in one step with git city land --delete.


prune

git city prune [--yes] [--dry-run]

prune is the cleanup half of the keep-by-default land. It deletes every branch you have landed — locally and on the remote — and nothing else:

  • The branch must be flagged landed (only land sets it).
  • It must have no commits of its own ahead of its parent — its work is wholly merged. Commit to a landed branch again and it is ahead once more, so prune skips it until you re-land.
  • It must have no children, so pruning can never orphan a stacked branch.

Because it deletes branches, prune prints its plan and asks for confirmation (--yes / -y to skip, required non-interactively), refuses on a dirty working tree, and — like everything else — is reversible with git city undo. With nothing to remove it just prints no landed branches to prune.

git city prune --dry-run     # see exactly which branches would go
git city prune               # confirm, then delete the landed branches

Errors

All errors print as a clean git-city: <message> on stderr with exit code 1 — never a raw traceback.

Situation What happens
Working tree is dirty Refused. Commit or stash first.
Feature is behind its parent Refused. Run git city sync, then land again.
Target is a trunk, not a feature Refused. Only features can be landed.

Undo

Landed by mistake? With the default keep behavior the branch is still there — just git city undo to rewind the parent (and clear the landed flag), or simply keep working on the branch. undo reverses the last git-city command: it restores moved refs and, for land --delete, recreates the deleted feature branch and can even bring back a force-pushed or deleted remote branch git-city itself created. Undo is single-level (only the most recent command), refuses on a dirty working tree, and refuses to destroy commits that exist on no other branch.

→ undo and recovery


  • sync — rebase a feature onto its parent; required before landing.
  • prune — delete the branches you've landed once their work is in the parent.
  • delete — remove a branch without merging its commits into the parent.
  • undo and recovery — reverse a land (or any other command).
  • the mental model — trunks, features, parents, and stacks.