The Quest Begins (The "Why")
I still remember the first time I tried to hunt down a bug that had been lurking in our codebase for weeks. The commit history looked like a cryptic grocery list:
fix typo
update stuff
more changes
When I finally git blamed the offending line, all I got was a vague “update stuff” from three months ago. I spent an hour staring at the diff, wondering why someone had changed that particular condition, and ended up rewriting the same logic myself because I had no clue what the original intent was. It felt like wandering through a dungeon without a map—frustrating, time‑consuming, and honestly a little embarrassing.
That experience sparked a question: What if every commit told a story instead of just leaving breadcrumbs?
The Revelation (The Insight)
The game‑changer for me was learning to treat a commit message like a short, useful memo to my future self (and to anyone else who might read the repo). The best practice that changed everything is simple:
Start with an imperative, 50‑character‑or‑less summary that answers “What did this change do?”, then follow with a blank line and a body that explains why the change was necessary.
Why does this work?
- The subject line gives a quick skim‑able overview in tools like
git log --onelineor GitHub’s PR list. - The body provides context that a diff alone can’t show: the problem you were solving, any trade‑offs considered, and links to tickets or design docs.
- When you’re looking at a commit six months later, you can instantly grasp the intent without replaying the entire diff in your head.
It’s like having a map with landmarks instead of just a bunch of footprints.
Wielding the Power (Code & Examples)
Let’s look at a real‑world scenario: I’m fixing a null‑pointer bug in a user‑profile service.
❌ The “Before” (the struggle)
fix NPE
That’s it. No clue what triggered the null, no hint about the surrounding logic, no reference to the ticket that reported it. Six months later, a teammate sees this and has to guess whether the fix was about input validation, a missing default value, or a race condition.
✅ The “After” (the victory)
Fix null‑pointer exception when profile picture URL is missing
- The `getProfilePicUrl()` method returned null for users without an uploaded image,
causing the downstream image‑loader to throw NPE.
- Added a fallback to the default avatar URL and added a unit test covering the empty‑string case.
- Resolves issue #1245.
Now the subject line tells you what changed (fixed an NPE under a specific condition). The body explains why it happened, what the fix entailed, and ties it back to the issue tracker. A future reader can scan the subject, decide if it’s relevant, and then dive into the body only if they need the details.
Common Traps to Avoid
| Trap | What it looks like | Why it’s problematic |
|---|---|---|
| Vague subject |
update code, fix bug
|
Gives zero context; forces readers to open the diff to understand intent. |
| Missing body |
Add validation for email field (no blank line, no explanation) |
Leaves out the reasoning; you lose the “why” that prevents regressions. |
| Overly long subject | Fixed the null‑pointer exception that occurs when the user profile picture URL is null or empty string in the getProfilePicUrl method which was called from the avatar service during render |
Breaks the 50‑character guideline, gets truncated in UI, and hurts readability. |
| No issue reference | Refactor user service |
Makes it hard to trace back to product decisions or design docs. |
Avoiding these traps turns your commit log from a mystic scroll into a clear, searchable changelog.
Why This New Power Matters
When you start writing messages this way, a few magical things happen:
-
Faster debugging –
git bisectorgit blamepoints you to a commit whose subject already tells you the likely cause. No more guessing games. - Better code reviews – Reviewers can see the motivation up front, ask smarter questions, and approve with confidence.
- Cleaner release notes – You can generate a changelog directly from commit subjects, saving hours of manual summarising.
- Team empathy – Future contributors (or even you, six months later) feel respected because you left a trail of reasoning, not just code.
I’ve seen teams cut their bug‑triage time in half after adopting this habit. It’s not just a “nice‑to‑have”; it’s a force multiplier for productivity and code quality.
Your Turn – Embark on Your Own Quest
Try it on your next PR: write a subject line that starts with a verb (Add, Fix, Refactor, Remove) and keep it under 50 characters. Then add a blank line and a brief body that answers why the change was needed, any trade‑offs you considered, and a link to the relevant ticket or documentation.
Give it a shot and watch how your commit history transforms from a cryptic log into a readable narrative.
What’s the most memorable commit message you’ve ever written (or read)? Drop it in the comments—I’d love to hear your stories! 🚀
Top comments (0)