ADR 0003: Single repo with machine_type templating, not branches¶
- Status: Accepted
- Date: 2025-04-12
Context¶
Personal and work Macs need overlapping but not identical configuration. Personal machines get Steam, Tidal, crypto wallets; work machines skip them. Both share the bulk of CLI tools, dev apps, and macOS defaults.
Options:
- One repo, conditional templating on a
machine_typevariable. - Separate
personalandworkgit branches with cherry-picks between them. - Separate repos.
- A
personal/subdirectory layered on top of abase/directory.
Decision¶
Option 1: a single repo with a machine_type prompt at chezmoi init time, stored in chezmoi's persistent state. Templates branch on {{ if eq .machine_type "personal" }}…{{ end }} where they need to.
Rationale¶
- One source of truth. A change to a shared file (most files) is made once and lands on every machine. No cherry-picking between branches.
- Visible diff between modes. Conditional blocks are inline and grep-able.
git grep 'eq .machine_type'enumerates every machine-type-specific decision. - No merge tax. Branches drift; merges become a chore. A single
mainwith conditionals never accumulates the merge debt. - Init-time, prompt-once.
promptChoiceOncewrites the answer into chezmoi's state file. Subsequentchezmoi applyruns don't re-prompt. New machines pick a value once; existing machines keep theirs. - Composable with
.chezmoi.arch. The same conditional pattern handles Apple Silicon vs Intel for credential helpers and GPG paths — no separate mechanism needed.
Alternatives rejected¶
- Branches — duplication, merge churn, divergence over time. Doesn't compose well with arch differences (would need 4 branches: personal-arm, personal-intel, work-arm, work-intel).
- Separate repos — same downsides plus operational overhead (two CIs, two pre-commit setups, two README updates).
- Layered directories — chezmoi has no native "layer" concept; would require custom apply scripts and bespoke conflict resolution.
Consequences¶
- Templates have visible conditional blocks, which is more verbose than a flat file. Acceptable trade for the alternatives' costs.
- A new machine type (e.g.
client-laptop) means adding it to the prompt's allowed values and auditing every existing conditional. Today there are ~10 conditionals; this remains tractable. - Test/CI burden grows: every
.tmplis rendered forpersonal × work×arm64 × amd64(4 cells) bymake verify-templatesand the CI matrix. This is the right cost — without it, a typo on one branch wouldn't be caught until that machine type was used.