How to Write Better Git Commit Messages
Dev Nexus5 min read
A practical guide to writing Git commit messages your future self will thank you for — the right structure, tense, and level of detail.
Every commit you make is a note to the next person who reads the code — and that person is usually you, six months from now, trying to work out why a line exists. A good commit message turns your history from a wall of noise into readable documentation.
This guide covers what actually makes a commit message good: the structure, the tense, and the difference between describing what changed and explaining why. None of it requires extra tooling or ceremony — just a few habits that compound over the life of a project.
The Problem
Most commit messages are written in a hurry, at the end of a task, when the last thing you want to do is write prose. So they come out as update, fix stuff, wip, or changes — messages that describe nothing.
The cost shows up later. When a bug is traced back to a commit and the message is fix, git blame tells you who and when but not why. You end up reverse-engineering intent from the diff, or worse, re-breaking something because you couldn't tell the change was deliberate.
A vague history also makes code review harder, pollutes release notes, and defeats tools that build changelogs from your commits. The information you needed was in your head at commit time — it just never made it into the message.
The Solution
A good commit message follows a simple, stable shape:
- A subject line in the imperative mood, kept short (around undefined characters).
- A blank line.
- A body that explains the reasoning, wrapped at about undefined characters — included only when the change needs it.
The imperative mood is the one convention people trip on. Write the subject so it completes the sentence "This commit will…": add rate limiting to the login route, not added or adds. It matches the style Git itself uses for generated messages like Merge and Revert.
The body is where the real value lives. The diff already shows what changed; the body records why — the bug you were fixing, the trade-off you accepted, the constraint that forced the approach. If you want a fast first draft that already follows this structure, paste your change into the Commit Message Generator and refine from there. And when you're staring at an unfamiliar diff you need to describe, the Code Explainer can help you understand it before you write the message.
Step-by-Step Guide
- 1
Write the subject in the imperative mood
Start with a verb that gives a command:
add,fix,remove,refactor,rename. The test is that your subject should fit the sentence "This commit will _". Sofix null check in parserpasses, whilefixed null checkandfixing parserdon't. Consistency here makesgit logread like a clean list of actions. - 2
Keep the subject short and specific
Aim for about undefined characters and stay under undefined — Git and GitHub truncate longer subjects in logs and lists. "Specific" beats "complete":
handle empty cart in checkouttells you more thanfix bug. If you can't summarise the change in one line, that's often a sign the commit is doing too much. - 3
Add a body that explains why
Leave a blank line after the subject, then explain the reasoning in plain sentences. Focus on context the diff can't show: why this approach, what alternative you rejected, what ticket or incident prompted it. A reviewer or your future self reads the body to understand intent, not mechanics.
- 4
Commit one logical change at a time
A focused commit is easy to describe; a sprawling one isn't. If your subject needs the word "and" —
add cache and fix typo and update deps— split it into separate commits withgit add -p. Small, single-purpose commits also make reverts and bisects far less painful. - 5
Review the message before you commit
Run
git diff --stagedand read your message against it. Does the subject match what actually changed? Does the body explain anything the diff doesn't? Thirty seconds of review now saves an archaeology session later. A generated draft is a fine starting point, but you own the final wording.
Common Mistakes
Using past tense or gerunds
added login,fixing bug,updates readme— these read inconsistently against Git's own imperative style. Switch toadd login,fix bug,update readme. It feels unnatural at first and then becomes automatic.Describing what instead of why
change timeout from 5s to 30sjust restates the diff. The useful version isincrease timeout to 30s for slow S3 uploads— now the reader knows the reason and won't "optimise" it back down later.Cramming everything into one commit
A single commit that touches ten unrelated things can't have an honest subject line. Break the work into logical commits so each message tells the truth and each change can be reverted on its own.
Writing subjects that are too long or too vague
Both extremes hurt.
fixsays nothing; a undefined-character subject gets truncated and buries the point. Put the essence in a tight subject and push the rest into the body.
Frequently Asked Questions
What tense should a Git commit message use?
The imperative present tense. Write the subject so it completes "This commit will…", for example `add caching layer`, not `added` or `adds`. This matches Git's own generated messages and keeps history consistent.
How long should a commit subject line be?
Around 50 characters, and no more than 72. Git tools and GitHub truncate longer subjects in logs and pull-request lists, so a concise, specific summary is more useful than a full sentence.
When should a commit have a body?
Whenever the reasoning isn't obvious from the diff. Trivial changes can be subject-only, but for anything with context — a bug's cause, a trade-off, a linked issue — add a blank line and a body that explains why.
Should I explain what the code does in the message?
No — the diff already shows what changed. Use the message to explain why: the motivation, the constraint, or the alternative you rejected. That's the information that isn't recoverable from the code itself.
Can a tool write good commit messages for me?
A generator can produce a well-structured draft in the right tense and length from your diff or summary, which saves time and enforces consistency. You should still review it, since only you know the true intent behind the change.
Try the Tool
Commit Message
Turn your diff into a clear, well-structured commit message in seconds.
Related Tools
Related Articles
Conventional Commits Explained
What Conventional Commits are, the full list of types, and why teams adopt the spec to automate versioning and changelogs.
Read articleAre UUIDs Really Unique?
In practice UUIDs never collide - here is the math behind why, and the one thing people get wrong: a UUID is an identifier, not a secret.
Read articleencodeURI vs encodeURIComponent Explained
The clear difference between encodeURI and encodeURIComponent, with examples showing which one to use for a value versus a whole URL.
Read article