Writing Git Commits
Overview
Write clean, conventional commit messages that make history readable and reviewable.
Core principle: A commit message should let a reviewer understand why a change was made without reading the diff.
When to Use
- About to run
git commitorgit commit --amend - Writing a commit message for staged changes
- Squashing or rewriting commit history
- User asks to "commit this" or "make a commit"
Do NOT use for:
- Deciding what to stage (that's a code review concern)
- Merge commits auto-generated by git tooling
Commit Format
Follow Conventional Commits:
<type>(<scope>): <subject>
<body>
<footer>
Quick Reference: Types
| Type | Use for |
|---|---|
| feat | New feature |
| fix | Bug fix |
| docs | Documentation only |
| style | Formatting, whitespace, no logic change |
| refactor | Code change that neither fixes nor adds |
| perf | Performance improvement |
| test | Adding or correcting tests |
| chore | Maintenance, deps, build, CI |
| revert | Reverting a previous commit |
Rules
-
Subject line
- Imperative mood: "add", not "added" or "adds"
- No period at the end
- Max 72 characters
- Lowercase after the colon
-
Body (optional)
- Wrap at 72 characters
- Explain why, not what (the diff shows what)
- Blank line between subject and body
-
Footer (optional)
- Breaking changes:
BREAKING CHANGE: <description> - Issue refs:
Closes #123,Fixes #456
- Breaking changes:
Example
Good:
fix(auth): prevent login when session cookie is expired
Sessions were validated by presence, not expiry time, allowing
stale cookies to authenticate users after logout.
Adds an explicit expiry check in validate_session() and a
regression test covering the expired-cookie path.
Closes #284
Bad:
fixed stuff
Why bad: no type, no scope, no context; "stuff" is unsearchable.
Workflow
- Run
git statusandgit diff --stagedto see what is actually committed - Identify the dominant change type (feat/fix/docs/...)
- Choose the narrowest meaningful scope (module, file, or component name)
- Draft subject, verify under 72 chars and imperative mood
- Add body only if the "why" is not obvious from the diff
- Reference issues in the footer when they exist
Common Mistakes
| Mistake | Fix |
|---|---|
| Vague subjects ("update") | Name the concrete change and module |
| Describing the diff in body | Explain motivation and trade-offs instead |
| Multiple unrelated changes | Split into separate commits |
| Past tense ("added") | Use imperative ("add") |
| Overly wide scope ("app") | Use the affected module or file |
Red Flags - STOP Before Committing
- Subject does not start with a known type
- Subject over 72 characters
- Mixing unrelated changes in one commit
- Message could describe any commit ("improve code")
Any of these: rewrite the message before committing.
