Skip to content

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), or git-city.toml in the same directory. Use it for preferences you want across every repository.
  • A local, committable file at <repo>/git-city.toml (or .git-city.toml if 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 = "main"
remote = "origin"
perennials = ["release", "staging"]

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:

git config git-city.branch.add-login.parked true
git config git-city.branch.add-login.private true

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.

Branch types & flags


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.

git-city vs git-town


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.

git city config


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.

git city init --trunk main

git city init


For the complete list of keys, their types, defaults, and precedence rules, see:

Configuration reference