Skip to content

Branch types & flags

git-city models your repository with just two kinds of branch — a trunk and a feature — plus a couple of optional modifier flags (parked, private) that tune how a feature is synced. That is the whole vocabulary. There is no "contribution", "observed", or "prototype" branch type to learn; everything you work on is a feature, and the flags handle the handful of exceptions.

This page is the reference: what each type and flag means, and exactly how sync and land treat it. For the bigger picture of why the model is shaped this way, read the mental model.


Branch types

Type What it is How sync treats it How land treats it
trunk A long-lived branch: the configured trunk (main/master) plus any perennials. Never rebased, has no parent, and fast-forwards from its remote. Fetches, then fast-forwards to its remote (or rebases local commits onto the remote). Not landed itself. It is the target that features land into — land fast-forwards the trunk to the feature's tip.
feature Everything you actively work on. It records a parent (another feature, or the trunk) in Git config, forming a tree rooted at the trunk. Rebases onto its (recursively up-to-date) parent, after absorbing any remote commits, then force-pushes with --force-with-lease. Fast-forwards its parent to the feature's tip, re-homes the feature's children onto that parent, pushes the parent, and keeps the feature (flagged landed; --delete removes it locally and on the remote).

A feature's parent is stored as git-city.branch.<name>.parent. Follow parents upward and you reach the trunk; a path down that tree is a stack.

Trunks are never rebased

A trunk only ever moves forward. sync will fast-forward it to its remote (or rebase your local commits onto the remote), but it will never rewrite published trunk history. Features are the only branches git-city rebases.

You can see both types at a glance in the tree, where the trunk is tagged (trunk) and the current branch is marked with a filled dot:

main  (trunk)
└─ api  ↑3 ↓0
   └─ ● ui  ↑2 ↓0

The mental model


Modifier flags

Two boolean flags refine how sync handles a feature. They are stored per-branch in Git config and are entirely optional — an unflagged feature is the common case.

Flag Git config key What it means Effect on sync
parked git-city.branch.<name>.parked Temporarily set aside. The branch is skipped by sync (including sync --all). Park a branch you don't want disturbed while you work elsewhere.
private git-city.branch.<name>.private A local-only branch you don't want published. Synced (rebased onto its parent) like any feature, but never pushed to the remote.

In the tree, an active flag shows up as a tag next to the branch — for example parked or private — alongside the ahead/behind counts and diverged where relevant.

A third marker, landed (git-city.branch.<name>.landed), is not a sync modifier but a bookkeeping flag: land sets it when it keeps a branch it has integrated, it shows up as a landed tag, and prune deletes the branches that carry it once their work is wholly in the parent. Unlike parked and private, you never set it by hand.

A branch can also carry a sync-strategy (git-city.branch.<name>.sync-strategy = rebase | merge, default rebase). Set it to merge and sync merges the parent in rather than rebasing onto it — the right call for a long-lived branch against a busy parent. A merge tag marks such branches.

No toggle command yet

There is no git city park / private command yet — the flags are read by sync but set by hand. Use git config for now:

# park a branch (skipped by sync)
git config git-city.branch.add-login.parked true

# mark a branch private (synced, never pushed)
git config git-city.branch.add-login.private true

# clear a flag
git config --unset git-city.branch.add-login.parked

These keys are local to your clone — they live in Git config, not in a tracked file, so they never cause churn for your collaborators. Dedicated park/unpark/private commands are on the roadmap.


How the flags interact with each command

  • sync / sync --all — honors both flags: parked branches are skipped entirely; private branches are rebased onto their parent but not pushed.
  • land — operates on a feature regardless of its flags; landing fast-forwards the parent and keeps the feature (flagged landed, or removed with --delete). (land refuses only if the feature is behind its parent — sync first.)
  • Everything else (new, switch, reparent, insert, delete, squash, undo) — treats a flagged feature like any other feature. The flags exist specifically to shape sync's push/rebase behavior.

Where this data lives

Branch types and flags are not configuration file settings — they are per-branch Git config, distinct from the global/local TOML that holds trunk and perennials:

Data Stored in
Which branch is the trunk; perennials TOML — global config.toml merged with local git-city.toml
A feature's parent, parked, private, landed, sync-strategy Git config — git-city.branch.<name>.{parent,parked,private,landed,sync-strategy}

Configuration reference