Skip to content
WestScript
Commit messages your future self can read

WestScript Editors@build-notesPosted

Commit messages your future self can read

Most commit messages are written in a hurry, at the end of a task, by someone who wants to move on. Most are read much later, by someone confused, staring at a line of code and running git blame to find out why it is there. Very often those two people are the same developer, a year apart.

A good commit message is a small kindness to that future reader. It does not take long to write, and it is one of the few kinds of documentation that is attached to exactly the code it describes. Here is how we would approach it.

What a commit message is for

The diff already shows what changed. Anyone can read it. What the diff cannot show is why: the bug report that prompted the change, the option you tried first and rejected, the constraint that made the obvious approach wrong.

So the main job of a commit message is to carry the information that is not in the code. If your message only repeats the diff in English ("change timeout from 30 to 60"), it adds almost nothing. If it says "raise timeout to 60s; the export endpoint takes up to 45s on large accounts", the next person to touch that number knows what they are dealing with.

A subject line that works in a list

The first line of a commit message is the one people see most, in git log --oneline, in pull request lists and in shortlogs. Some conventions make it work well in those places:

  • Keep it short. Around 50 characters is a common target; much past 70 and many tools will truncate it.
  • Use the imperative mood. "Fix crash when cart is empty", not "Fixed crash" or "Fixes crash". It reads like an instruction the commit carries out, and it matches the messages Git itself generates, such as "Merge branch ...".
  • Say what changes in behaviour. "Update utils.js" tells nobody anything. "Round prices to cents before summing" does.
  • Skip the trailing full stop. It is a title, not a sentence.

Here is the difference in a log:

code
a1c3f9e fix
7be2d10 wip
4d9a0c2 more fixes

a1c3f9e Round prices to cents before summing
7be2d10 Show empty-cart message instead of a blank page
4d9a0c2 Retry payment webhook once on timeout

Only the second log is useful six months from now.

A body that explains why

Not every commit needs a body. A typo fix does not. But anything that involved a decision deserves a few lines. Leave one blank line after the subject (Git and many tools rely on it to separate the two), then write in plain prose, wrapped at around 72 characters so it reads well in a terminal.

code
Round prices to cents before summing

Line totals were summed as floats and rounded once at the end,
so some carts showed a total one cent off from the sum of the
lines on the receipt.

Round each line to cents first, then sum. Totals now match the
receipt. Tax is still calculated on the rounded subtotal, as
before.

A useful structure for the body is: what was wrong, what this commit does about it, and anything surprising a reviewer should know. To write a message like this, run git commit without -m so Git opens your editor; a one-line -m flag quietly discourages anything longer than a subject.

One change per commit

A commit message is only as clear as the commit it describes. If a single commit fixes a bug, renames a module and reformats three files, no message can describe it well, and nobody can revert just the bug fix later.

Before committing, look at what is staged. git add -p lets you stage a file hunk by hunk, so you can split unrelated edits into separate commits even when they live in the same file. If you find yourself writing "and" in a subject line, that is often a sign the commit wants to be two.

Tidy up before you share

While you work, messy commits are fine. "wip" and "try again" are honest notes to yourself. The time to clean up is before the branch is reviewed or merged, while the history is still yours alone.

Git has a pair of features made for this. When you notice a mistake in an earlier commit on your branch, commit the fix with:

bash
git commit --fixup=<commit>

Later, run an interactive rebase with autosquash, and Git will place each fixup right after the commit it belongs to and fold it in:

bash
git rebase -i --autosquash main

Only rewrite history that nobody else has based work on. Once a branch is shared, rebasing it changes commit IDs under other people's feet. If your team squashes pull requests on merge, the pull request title and description become the commit message, so give them the same care.

Conventions are optional, consistency is not

Some projects use structured formats, such as a type prefix (fix:, feat:) or trailers at the end of the body for linked issues and co-authors. These can be useful, especially when tools generate release notes from the history. But a structured message with a vague subject is still a vague message.

Whatever style you choose, write it down in the project's contributing notes and stick to it. A history where every message follows the same shape is far easier to scan than one where each contributor invented their own.

And if a commit taught you something worth sharing, such as an odd bug or a neat Git trick, it may be worth turning into a post. A short write-up like a "Today I Learned" post is a good fit for the small ones.

Discussion 0

Replies are reviewed before they appear.

Write a reply

Plain text, up to 2,000 characters. No account or email needed; a moderator reviews each reply first.

No replies yet. Found a typo, a better approach or a step that failed for you? Start the thread.