Skip to content

Consider: declarative git-config template vs. current imperative scripts #290

Description

@laurigates

What

Decide whether the git config under ~/.config/git/config should be managed as a single declarative chezmoi template (.tmpl), or kept as the current additive imperative scripts.

This is a follow-up to the per-location identity work (includeIf) landed in:

  • private_dot_config/git/personal.inc (declarative — personal identity)
  • run_onchange_after_10-git-identity.sh (imperative — default identity + includeIf directives)

Why (the crux)

~/.config/git/config is written by three independent sources today:

  1. run_once_before_00-initial-setup.sh — base settings (pager, merge, push, lfs, rerere…), one-time, via git config --global
  2. gh auth — the [credential "https://github.com"] / gist helper blocks, at runtime (not chezmoi)
  3. run_onchange_after_10-git-identity.sh — default FVH identity + four includeIf overrides

Because gh co-owns the file at runtime, a static .tmpl (which is authoritative for the whole file) forces a decision about the gh credential helper: bake it into the template (chezmoi owns gh's territory, incl. the macOS-only /opt/homebrew/bin/gh path), or omit it and have chezmoi apply delete it → breaks auth. This is the runtime-drift trap from ~/.claude/rules/chezmoi-conventions.md.

Options

A. Keep imperative run_onchange (current state)

  • Additive: only writes the keys it owns; never rewrites the whole file.
  • Drift-immune by construction; leaves gh's helper + ad-hoc git config --global untouched.
  • Consistent with the existing run_once pattern.

B. Full declarative template consolidation

  • One private_dot_config/git/config.tmpl = base settings + identity + includeIf + gh helper (path via {{ if eq .chezmoi.os "darwin" }}).
  • Delete the git config --global block from run_once_before_00.
  • Delete run_onchange_after_10-git-identity.sh.
  • One-time cost: removing the run_once git block changes that script's hash → re-runs the heavy run_once (nvim Lazy sync, Mason, pre-commit install) once.

C. modify_ script (jq-style merge)

  • The idiomatic chezmoi answer for runtime-mutated files — but git config is INI, not JSON, so there's no clean merge primitive. More complex than A or B. Not recommended.

Comparison

A: imperative run_onchange B: static .tmpl
Readability scattered across 2 scripts; includeIf.gitdir:….path key-mangling is ugly one file, natural [includeIf "…"] blocks
chezmoi diff shows script text, not resulting config shows real config content diffs
gh credential helper untouched (additive) must bake in (+ darwin conditional) or it gets deleted
Ad-hoc git config --global preserved clobbered on next apply
Cross-platform identity/includeIf already portable handles macOS-only gh path via conditional
Consolidation cost none forces one heavy run_once re-run
Drift-immune by construction yes no (only as stable as gh's behavior)

Decision factors

  • The gh-helper drift risk is low in practice — gh writes it once and leaves it. So B is defensible, just a bigger/more opinionated move than the problem strictly requires.
  • Lean A if keeping gh's credential setup as gh's territory and avoiding any clobber risk matters more than single-file readability.
  • Lean B if one readable source of truth for all git config is the priority, and chezmoi owning the gh helper line is acceptable.

Recommendation

Keep A for now (additive is the correct response to a gh-co-owned file). Revisit B as a deliberate consolidation if/when the scattered-config readability becomes a real annoyance.

Acceptance criteria

  • Decision recorded (A / B / C) with rationale
  • If B: config.tmpl faithfully reproduces current content incl. gh helper, run_once git block + run_onchange removed, chezmoi diff clean after apply, identity verified per-location
  • If A: this issue closed as "won't change" with the rationale captured

Reference

  • ~/.claude/rules/chezmoi-conventions.md — Runtime Drift + modify_ guidance
  • git includeIf / gitdir: docs

Metadata

Metadata

Assignees

No one assigned

    Labels

    choreMaintenance, deps, refactoringenhancementNew feature or improvementquestionFurther information is requested

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions