skip to content

What does Git's commit.template setting do, and how far can it enforce a convention?

level: seniorimportance: nice to knowfreq 30%

answer

  1. it fills the editor, nothing more
  2. comment lines never reach the message
  3. config is not part of a clone
  4. one flag skips the editor entirely
  5. guidance versus a gate

basics

~20 s

commit.template names a file whose contents pre-fill the editor when you run git commit. It is a prompt, not a check: the author can delete every line, -m skips it entirely, and the setting lives in local config that a clone does not carry.

solid answer

~50 s

`commit.template` points at a file — commonly a `.gitmessage` checked into the repository — whose contents Git loads into the editor buffer as the starting message; `git commit -t <file>` does the same for one invocation. It is purely a prompt. Lines starting with the comment character (`#`, or whatever `core.commentChar` is set to) are stripped from the final message, so the template can carry instructions that never reach history. Three limits matter. Config is per-clone and is **not** transferred by `git clone`, so each developer must set it or run a bootstrap step. `git commit -m` bypasses the editor and therefore the template. And nothing validates what is finally written. Real enforcement needs a `commit-msg` hook locally plus a check in the pipeline, since hooks are not distributed either. Use the template to make the good message easy, and a check to make the bad one fail.

code

ini · 4 lines
ini
[commit]
	template = .gitmessage
[core]
	commentChar = ";"

go deeper

for a junior

Know that commit.template just pre-fills the commit editor from a file, and that its commented lines are stripped from the message you end up with.

for a middle

Explain why it cannot enforce anything: config is per-clone and not cloned, -m bypasses the editor, and nothing validates the result.

for a senior

Lay out the layered approach you would actually deploy — template to guide, commit-msg or prepare-commit-msg hook for fast feedback, and a check outside the developer's machine for the guarantee.

for a principal

Weigh the cost of enforcement against the behaviour you want: mandatory formats reliably produce conforming but empty messages, so decide where a gate is warranted and where culture and review do more.

## What the setting does `git config commit.template /path/to/file` tells `git commit` to seed the editor buffer with that file's contents instead of starting empty. `git commit -t <file>` is the per-invocation equivalent. That is the entire mechanism: text appears in the editor, and whatever the author leaves behind becomes the message. A typical template is a skeleton plus commented guidance: ``` # Subject: imperative, ~50 chars, no trailing period # # Why is this change needed? What was the behaviour before? # Body wrapped at 72 columns. # # Trailers (last paragraph, one per line): # Refs: PROJ- # Co-authored-by: Name <email> ``` Lines beginning with the comment character are stripped when the message is saved, so the guidance is visible while writing and absent from history. `core.commentChar` changes that character, which matters if your messages legitimately begin with `#`. The `--cleanup` modes control the stripping: `strip` removes comments and trailing whitespace, `whitespace` keeps comments, `verbatim` keeps everything as typed, and `scissors` keeps text above a scissors line. ## Why it is not enforcement **Config does not travel.** `git clone` copies objects and refs, not configuration. You can commit `.gitmessage` to the repository so the file is present, but every developer still needs `git config --local commit.template .gitmessage` on their clone. Teams handle that with a documented setup step or a bootstrap script; there is no way to make a clone adopt it automatically. **The template is optional in practice.** `git commit -m "quick fix"` never opens an editor, so the template plays no part. Neither does any tool or IDE that composes a message its own way. **Nothing checks the result.** The author can select all and delete. Git will happily record a one-word message. So `commit.template` belongs to the class of interventions that lower friction for people who already want to comply. That is genuinely valuable — most bad commit messages come from not knowing what to write, not from refusing to — but it is not a control. ## What actual enforcement looks like The local mechanism is the `commit-msg` hook: it receives the path to the prepared message file, can inspect or rewrite it, and a non-zero exit aborts the commit. That gives immediate feedback at the right moment. Its limitation is the same distribution problem: hooks live in `.git/hooks`, which is not cloned, so they must be installed by a setup step, and any developer can bypass them. Because of that, the enforcing check has to exist somewhere the author does not control — a job that inspects the messages of the commits being proposed, or a server-side hook on the receiving repository that refuses a push whose commits do not conform. The local hook is then a fast-feedback convenience rather than the gate. The related `prepare-commit-msg` hook runs earlier, before the editor opens, and can populate the buffer programmatically — injecting a ticket id parsed from the branch name, for instance. That is often more useful than a static template, because it fills in the part the author would otherwise mistype. ## Designing the template itself - Keep it short. A 40-line template gets skimmed and ignored; six lines of prompts get read. - Prompt with questions, not headings. "Why is this needed?" produces prose; "Description:" produces a restatement of the diff. - Leave the first line blank so the author's cursor starts on the subject. - Do not encode anything a hook could fill in automatically. ## The judgement being tested An interviewer asking this is usually probing whether you distinguish *making the right thing easy* from *making the wrong thing impossible*, and whether you know which Git mechanisms are distributed with a repository and which are not. The complete answer is layered: a template to guide, a `prepare-commit-msg` or `commit-msg` hook installed by a setup step for fast local feedback, and a check outside the developer's machine for the guarantee — with the honest caveat that a convention nobody sees the value of will be satisfied minimally no matter how it is enforced.

  • Does checking .gitmessage into the repository make the template active for everyone?
    No. Cloning copies objects and refs, never configuration, so the file arrives but `commit.template` is unset. Each developer has to point at it with `git config --local commit.template .gitmessage`, usually via a documented setup step or a bootstrap script. There is no mechanism for a repository to impose config on its clones.
  • Why do template comment lines not appear in the final message?
    Git strips lines starting with the comment character — `#` by default, configurable through `core.commentChar` — when it cleans up the message. The `--cleanup` mode governs this: `strip` removes comments and trailing whitespace, while `verbatim` keeps everything exactly as typed, which would leave the guidance in your history.
  • If you needed the convention actually enforced, what would you add?
    A `commit-msg` hook for immediate local feedback, installed by a setup step since hooks are not cloned, plus a check the author cannot bypass — either a job that validates the messages of the proposed commits or a server-side hook that rejects a non-conforming push. The local hook is convenience; the remote check is the guarantee.

saying these in an interview costs you the question

  • Thinks commit.template validates or rejects messages
  • Assumes cloning a repo applies its config
  • Forgets that -m skips the template entirely
  • Believes hooks are distributed with the repository
  • Treats a template as sufficient enforcement for automated versioning

context