How would you roll out a standard Git configuration across a team, given .git/config is untracked?
answer
- you cannot commit .git/config
- config can name programs to run
- a tracked fragment plus a one-time opt-in
- machine image or dotfiles for personal defaults
- only the receiving side can enforce
basics
~20 sShip a tracked config fragment in the repository and have each clone reference it once with git config include.path, provision personal defaults through dotfiles or a system file, and enforce anything that actually matters with server-side hooks rather than trusting client configuration.
solid answer
~50 sGit deliberately never reads configuration from a repository's tracked files, because config can name programs to execute. So a team standard needs two halves. For repository-scoped settings, commit a fragment such as `.gitconfig-shared` and have each developer run `git config include.path ../.gitconfig-shared` once — include paths resolve relative to the file containing them, so from `.git/config` that points at the worktree root, and the fragment stays reviewable in the repository. For personal defaults — aliases, editor, identity — provision `~/.gitconfig` from a dotfiles repository or bake a system-wide `/etc/gitconfig` into the machine image or container. Crucially, none of this is enforcement: a developer can unset any of it, so anything that must hold — required trailers, forbidden refs, file-size limits — belongs in a server-side `pre-receive` or `update` hook, where declining the push is the only control that cannot be bypassed. Verify a rollout with `git config --show-origin --list` rather than assuming.
code
bash · 5 lines# one-time opt-in per clone, usually inside the project's setup script
git config include.path ../.gitconfig-shared
# prove it took effect
git config --show-origin --list | grep gitconfig-sharedgo deeper
Know the basic fact this rests on: .git/config is not tracked, so it never travels with a clone, and a teammate does not get your settings by pulling.
Explain the include.path trick with a tracked fragment, why the path resolves relative to .git/config, and that it requires one explicit opt-in command per clone.
Show the layering — repository fragment, provisioned personal defaults, machine-wide baseline — and insist that anything mandatory is checked server-side because client configuration is always bypassable.
Own the tradeoff: name the security reason for the trust boundary, decide what the organisation may impose versus what stays personal, and design the verification that stops the rollout decaying silently.
## Why there is no simple answer New engineers reasonably expect to be able to commit `.git/config`. Git will never allow it, and the reason is security: configuration can specify commands that Git executes — hook paths, clean and smudge filters, the transport command used for SSH, and more. If cloning a repository could install configuration, cloning would be equivalent to running arbitrary code from a stranger. The untracked `.git/config` is a deliberate trust boundary, and any distribution scheme has to respect it. ## Layer one: repository-scoped settings via an included fragment When the settings genuinely belong to the project, commit them as an ordinary tracked file, for example `.gitconfig-shared` at the repository root, and have each clone opt in once: `git config include.path ../.gitconfig-shared` Include paths are resolved relative to the config file containing the directive, so from `.git/config` the `../` reaches the worktree root. The effects are good: the fragment is reviewed like any other file, changes to it propagate on the next pull, and the opt-in is one explicit act by the developer rather than something a clone did silently. Wrap that one command in the project's setup script or bootstrap task so nobody has to remember it. The limitation is the opt-in itself. Someone who skips the setup step simply does not have the settings, and you will not know unless something checks. ## Layer two: personal and machine defaults Aliases, editor, pager, diff and merge preferences, and identity are properties of the human, not the project. These belong in `~/.gitconfig`, distributed the way you distribute any dotfile — a dotfiles repository, a provisioning tool, or an onboarding script. For fleets and CI images, `/etc/gitconfig` gives a machine-wide baseline that individual users can still override, which is usually the right relationship: the organisation sets a sensible floor, the individual keeps their own preferences. Conditional includes compose nicely here. A provisioned global file can carry `[includeIf "gitdir:~/src/company/"]` so that anything cloned into the company directory picks up organisational defaults, including the right commit identity. ## Layer three: what actually gets enforced The decisive point at senior level is that **client configuration is not a control**. Every one of these settings can be unset, overridden per repository, or bypassed with `git -c`. Client-side hooks are worse still: they live in `.git/hooks`, are not cloned, and are trivially skipped. If a rule matters — every commit carries a required trailer, nobody pushes a 500 MB blob, certain refs are off limits — it has to be checked where the objects arrive. A server-side `pre-receive` or `update` hook inspects what is being pushed and rejects it; that is the only decision a developer's machine cannot overrule. So the honest framing of a rollout is: client config for **ergonomics and defaults**, server-side checks for **requirements**. Presenting a client-config rollout as a compliance measure is the answer that fails the question. ## Verifying, and keeping it verified Roll-outs decay. Verify with `git config --show-origin --list` in a real clone — it names the file behind every value, so you can prove the include fired and the fragment is being read. A small check that runs during the project's setup or in CI ("is the expected key present in this environment?") turns silent drift into a visible failure. Keep the fragment small; a fragment nobody understands gets deleted the first time it surprises someone. ## The tradeoffs to name out loud - **Uniformity versus autonomy.** Imposing editors and aliases through a system file is technically easy and socially expensive. Impose what affects the repository's contents; leave taste alone. - **Opt-in versus automatic.** The include-path trick requires a step, which is exactly what makes it safe. Automating it inside a setup script is fine; wanting Git to do it on clone is wanting the trust boundary removed. - **Client convenience versus server truth.** Duplicating a server-side rule as a client-side convenience is good — it gives fast feedback — provided nobody mistakes the fast feedback for the enforcement. A strong answer covers all three layers, names the security reason `.git/config` is untracked, and lands on the conclusion that the only rules you can rely on are the ones checked when the push arrives.
- Why does Git refuse to read configuration from a repository's tracked files?Because configuration can name executables — hook paths, clean and smudge filters, the SSH transport command. If a clone installed configuration, cloning an untrusted repository would be equivalent to running its author's code. The untracked `.git/config` is a deliberate trust boundary.
- Why does include.path ../.gitconfig-shared work from .git/config?Include paths are resolved relative to the configuration file containing the directive. `.git/config` sits one level below the worktree root in a standard layout, so `../` reaches a tracked file there. It fails for repositories with a separate git directory, so treat it as a convention, not a guarantee.
- If a rule must never be violated, where does it belong?In a server-side `pre-receive` or `update` hook, which inspects the refs and objects being pushed and rejects the push. Client-side configuration and hooks can all be unset, overridden with `git -c`, or bypassed, so they give fast feedback but no guarantee.
- How do you keep a client-side rollout from silently decaying?Verify rather than assume: `git config --show-origin --list` in a real clone proves which file supplied each value. Put an assertion in the project's setup or CI that the expected keys resolve, so a developer who skipped the opt-in step gets a visible failure instead of quietly diverging.
saying these in an interview costs you the question
- Proposes committing .git/config into the repository
- Treats client-side config as an enforcement mechanism
- Assumes cloned repositories bring their hooks along
- Imposes personal preferences like editors fleet-wide by default
- Never verifies the rollout actually applied in a real clone