How to Write Professional Commit Messages
Good commit messages turn git history into documentation: they explain what changed and why, without making the next reader trawl through diffs. This post covers subject lines, optional bodies, Conventional Commits, and habits that keep messages clear for you and your team.
Why commit messages matter
A commit is more than a snapshot of files. It is a decision record: what you chose to change and—when you write well—why that choice made sense. Professional messages make code review faster, help newcomers ramp up, and keep git blame, git bisect, and release notes useful. Vague messages (“fix”, “wip”, “updates”) force everyone to open diffs to learn anything at all.
Investing one minute in the message often saves hours later.
The basic shape
Most teams converge on a simple layout:
- Subject line — single line, present tense / imperative mood, typically 50 characters or fewer as a soft limit so tools and terminals display it cleanly.
- Blank line — separates the subject from the body everywhere Git expects it (logs, emails, formats).
- Body — optional for tiny edits; encouraged when behavior, motivation, or rollout steps are not obvious from the diff alone. Wrap body text around 72 characters so plain-text readers stay readable.
Think of the subject as completing: “If applied, this commit will…”
Examples:
- “Add Redis-backed session store”
- “Reject negative quantities on cart update”
- “Align pagination controls with design tokens”
Avoid trailing punctuation on the subject if your style guide does (many teams skip the period).
Conventional Commits
Many projects prefix the subject with a type and optional scope:
<type>(<scope>): <short description>
Common types include:
| Type | Typical use |
|---|---|
feat | New capability users or operators notice |
fix | Bug fix |
docs | Documentation only |
style | Formatting, missing semicolons—no logic change |
refactor | Internal change without fixing a bug or adding a feature |
perf | Performance improvement |
test | Tests added or corrected |
build / ci | Tooling, pipelines, packaging |
chore | Maintenance that does not fit elsewhere |
Examples:
feat(auth): support refresh token rotationfix(api): return 422 on invalid ISO dateschore(deps): bump eslint to 9.x
Consistency matters more than the exact taxonomy: pick types your team will actually use.
Imperative mood
Write “Fix null dereference” not “Fixed” or “Fixes”. Imperative matches Git’s own generated messages (Merge branch…, Revert…) and reads like a command to the codebase. It stays short and avoids tense debates.
What belongs in the body
Use the body when:
- Motivation is not visible in the diff (policy change, incident response, ticket context—without inventing ticket numbers you do not have).
- You need to describe tradeoffs (“chose X over Y because…”).
- There are migration steps, feature flags, or follow-up work.
- You are removing code—say what replaced it or why it is safe.
For straightforward changes (“rename variable for clarity”), a subject alone is often enough.
Example body:
Replace synchronous file writes with a bounded queue so uploads
during traffic spikes do not block request threads. Max queue depth
defaults to 100; overflow returns 503 with Retry-After.
Tested: load test script in ops/load/upload-spike.js on staging.
Small commits, readable history
Professional practice usually favors many focused commits over one enormous squashed blob—each commit passes tests and represents one logical step. Reviewers can follow the narrative; git bisect finds the breaking change.
When your hosting workflow squashes on merge, rewrite the squash message so it still summarizes the whole change meaningfully—do not settle for a list of thirty subjects unless your tooling generates a good summary.
Anti-patterns to avoid
- Noise: “final”, “really fix”, “oops”.
- Only ticket IDs in the subject with no human-readable summary (fine to add IDs in the body or footer).
- Mixing unrelated changes in one commit—hard to describe honestly in one subject.
Summary
Professional commit messages combine a clear imperative subject, optional body for context, and consistent types when your team adopts Conventions. They respect the next reader—often you, weeks later—and keep history a trustworthy asset.
Rate this post
All fields are optional. Just stars is fine.