I’m a Conventional Commits person. The format is simple: <type>(<scope>): <description>, and the types (feat, fix, docs, chore, etc.) give you a scannable git log without any extra tooling.
The non-negotiables
To start with, these aren’t my rules, they’re git’s rules.
I just happen to agree with all of them…
- 50 characters max for the title. GitHub truncates anything longer, and
git log --onelinelooks terrible when titles wrap. This one comes from tpope’s classic 2008 post and it’s stuck around because it works. - Imperative mood. “Add feature”, not “Added feature”. Git itself does this (“Merge branch…”, “Revert…”), so your commits should match. This is part of the Conventional Commits spec and matches git’s own conventions.
- No trailing period on the title. It’s a title, not a sentence.
- Blank line between title and body. Skip this and tools will get confused. Just do it.
- Body lines wrap at 72 characters. Again,
git logandgit format-patchassume this width. Fight the urge to let lines run long.
This one’s not git’s specifically but since 99% of my work is Github based (both work and open source) it makes sense:
- Use
Closes #123orFixes #123for issue refs. GitHub will auto-close the issue when the commit lands. Free automation.
My personal quirks
On top of the standard stuff, I have some preferences that are just… mine:
- Bullets use
*not-. No real reason. I just like how it looks. - I lean toward always including a scope. The spec says it’s optional, but
fix(auth):tells you so much more than justfix:at a glance. - Body bullets explain “why”, not “what”. The diff already shows what changed. Tell me why you changed it.
- Stage files by name, never
git add .orgit add -A. I’ve been burned by accidentally committing.envfiles and fat binaries. Naming each file forces you to think about what you’re actually committing. - AI-assisted commits get a
Co-Authored-Byfooter. If Claude helped write the code, the commit says so. Transparency is good.
The template
feat(scope): imperative description under 50 chars
* Why thing one was changed
* Why thing two was changed
Closes #N
Co-Authored-By: Claude <noreply@anthropic.com>
Nothing fancy, just enough structure to keep things readable six months from now when you’re doing git blame at 2am trying to figure out why something broke.