Configuration¶
git-city keeps its configuration in two homes, deliberately. Project settings — which branch is your trunk, which branches are perennial — live in plain TOML files that you can read, edit, and commit. Per-branch state — each feature's parent and its modifier flags — lives in your local Git config, where it belongs to your clone and never churns a tracked file.
This page explains the split and why it exists. For the exact keys, their types, and defaults, see the configuration reference.
The two homes¶
| What | Where | Scope | Example |
|---|---|---|---|
Project settings (trunk, remote, perennials) |
TOML files | Global + local, committable | git-city.toml |
Per-branch state (parent, parked, private) |
Git config | Local to your clone | git-city.branch.add-login.parent |
The rule of thumb: if a fact is true for everyone working on the repository, it is a project setting and lives in TOML. If a fact is true only for your working copy — which feature descends from which, what you have parked — it is per-branch state and lives in Git config.
Project settings: TOML, global + local¶
Settings come from two TOML files, merged key by key, with local overriding global:
- A global file at
$XDG_CONFIG_HOME/git-city/config.toml(defaulting to~/.config/git-city/config.toml), orgit-city.tomlin the same directory. Use it for preferences you want across every repository. - A local, committable file at
<repo>/git-city.toml(or.git-city.tomlif you prefer a dotfile). Use it to pin settings for one project so your whole team shares them.
Either location accepts both names but only one at a time — having both is an error rather than a silent precedence guess.
A few keys live here:
trunk names your long-lived mainline. remote names the remote git-city pushes to and fetches from — worth setting when you have more than one (it defaults to origin, or the first remote otherwise). perennials lists any additional long-lived branches that behave like trunks — never rebased, always fast-forwarded from their remote. Everything else is a feature.
Local wins, key by key
The merge is per-key, not whole-file. If your global config sets perennials and a repo's local git-city.toml sets only trunk, you get the local trunk and the global perennials. A repo can override just the one key it cares about.
Malformed TOML
A broken TOML file produces a clean git-city: <message> error rather than a crash. Fix the syntax and rerun.
You normally don't hand-write the local file — git city init creates it for you (see below). Note that init writes only the local file; it never bakes your global values into the committed file, so your personal preferences stay personal.
Per-branch state: Git config¶
A feature's parent, and its modifier flags, are recorded under the git-city.branch.<name>.* namespace in your repository's Git config:
| Key | Type | Meaning |
|---|---|---|
git-city.branch.<name>.parent |
string | The branch this feature is stacked onto |
git-city.branch.<name>.parked |
bool | Skip this branch during sync |
git-city.branch.<name>.private |
bool | Sync with its parent, but never push |
git-city.branch.<name>.landed |
bool | Set by land; marks the branch for prune |
git-city.branch.<name>.sync-strategy |
rebase | merge |
How sync integrates the parent (default rebase) |
This data is intentionally local to your clone. Parentage describes the shape of your in-flight work, and it changes constantly as you stack, reparent, and land branches. Storing it in Git config keeps it out of your tree, so it never shows up in a diff and never causes a merge conflict with a teammate's stack.
The parent key is set for you by the commands that move commits — new, insert, reparent, and so on. The parked and private flags do not yet have dedicated CLI commands; set them by hand with git config for now:
What the flags do
A parked branch is left untouched by sync — useful when you want to freeze a branch while you focus elsewhere. A private branch is synced with its parent like any other feature, but is never pushed — useful for local-only scratch work. Both are respected by sync.
Why the split¶
Keeping these two homes separate is what makes git-city pleasant to live with:
- Committable settings, private state. The team agrees on the trunk once, in a committed file. Nobody's personal stack metadata leaks into the repository.
- No tracked-file churn. Reparenting a branch or parking it touches only your local Git config — never a file under version control — so routine workflow operations produce no diffs.
- Override where it counts. A global file carries your defaults across every repo; a local file lets one project override exactly the keys it needs.
Compared to tools that scatter everything across many Git-config keys, git-city's small global+local TOML keeps the shared, human-editable settings in one obvious, committable place — while the volatile per-branch bookkeeping stays quietly in Git config where it can't get in your way.
Inspecting your configuration¶
git city config prints the effective configuration — the resolved trunk, remote, and perennials — and the path to each config file, noting whether it exists:
trunk: main (auto-detected)
remote: origin (auto-detected)
perennials: (none)
global: /home/you/.config/git-city/config.toml (not present)
local: /path/to/repo/git-city.toml
This is the fastest way to confirm which trunk git-city is actually using and where it read its settings from.
Getting set up¶
In a new repository, run git city init once. It records the trunk in the local git-city.toml: it uses --trunk <name> if you pass it, otherwise it auto-detects main or master, or — on a terminal — shows an interactive dropdown of your branches.
For the complete list of keys, their types, defaults, and precedence rules, see: