Blog
Enforcing Git Commit Message Standards: A Simple Approach for Teams
- Date —
- April 21, 2025
- Updated —
- October 6, 2026
- Tags —
- Git, Engineering, Workflow
Note — Revised for clarity and flow; substantially shortened.
We put an automated check on our commit messages a while back. It is a shell script, it takes about a second to run, and it has done more for how our history reads than anything else we have tried.
Why bother
Commit messages are the only documentation on a project that nobody writes on purpose. Six months later, the record of why a decision was made is whatever someone typed into a box at 6pm on a Friday.
Readable commits help with the unglamorous parts of the job:
- Review, since the diff tells you what changed and the message tells you why
- Debugging, when you need to find when something broke rather than guess
- Changelog and version automation, which needs a format it can parse
- Onboarding, because new people read the history before they read the docs
What it enforces
The subject line has to start with a capitalised word, be in the imperative (“Add feature”, not “Added feature”), have no trailing period, and stay under 80 characters.
If you use Conventional Commits, the hook validates the type prefix too:
type: Subject line with verb
type is one of feat, fix, docs, style, refactor, perf, test, chore, build, ci, revert.
Longer messages need a blank line after the subject and should wrap at 72 characters. Describe the what and the why, not the how, since the diff already shows the how.
The three pieces
There is a commit-msg hook that does the checking, an imperative verbs list it validates the first word against, and an install script that wires it all up.
The verb list is the part I did not expect to matter. Forcing the first word to describe what the commit does rather than what you did sounds fussy, and it turned out to be the single most useful rule for writing clearer commit messages.
Installing it everywhere
The hook uses Git’s template system, so it is one line:
git config --global core.hooksPath ~/.git-templates/hooks
Install it once and every repository you clone afterwards inherits it.
What changed
Code review got faster, because the messages are consistent enough to scan without reading them properly. Our release tooling can generate changelogs from them now. New people pick up the conventions faster with the feedback arriving at commit time rather than at review time.
The bigger effect is that catching a formatting problem in a hook costs a second of your own attention. Catching it in review costs someone else’s attention, and that attention was the thing we were trying to protect.
If you want to try it
Explain the reasoning before you turn anything on. Start with warnings and only start rejecting once the warnings have been ignored long enough to prove people care. Expect to adjust the verb list, since ours reflects how we talk rather than any spec. And keep a few examples of good and bad messages somewhere people will actually find them.
The code
Everything is in my dotfiles repository, along with installation instructions and documentation.