{ } Programming

Clear commit messages: how to write them and why they matter

How to write useful commit messages: a short imperative subject, a body explaining why, atomic commits, and concrete examples of good and bad messages.

You open a project's history and find messages like "fix", "changes", "updated", "wip", "fix again". Six months later you need to understand why a certain line was changed, and the history tells you nothing. The commit message is one of the most underrated forms of documentation: it takes thirty seconds to write well and can save hours for whoever reads it, often yourself.

Who a commit message is for

The code says what the program does. A commit's diff says what changed. The message is the only place where you can explain why it changed. This information is valuable in very concrete situations:

  • during a code review, to understand the intent before reading the lines;
  • when you use git blame to find the origin of a suspicious line;
  • when you search git log for the commit that introduced a bug;
  • when you prepare the release notes for a new version.

The classic structure

A widespread convention in the Git community calls for:

  1. a short subject line, roughly within 50 characters and in any case no more than 72;
  2. a blank line;
  3. an optional body, with lines of reasonable length, that explains the context.
Prevent double submission of the order form

If the user clicked "Confirm" twice before the server responded,
two identical orders were created. The button is now disabled on
the first click and re-enabled if an error occurs.

The server-side check is still required: this change only reduces
the most common cases.

The blank line is not a whim: many tools treat the first line as the title and the rest as the description. Without the separation, the title becomes a whole paragraph.

The subject in the imperative

A useful habit is to write the subject as a command: "Add", "Fix", "Remove", "Rename". A trick to check it is to complete the sentence "If applied, this commit will…": "…add date validation" works, "…I sorted some stuff" does not. In English the imperative is the most widespread convention, partly because it is the form used by messages Git itself generates, such as "Merge branch".

More important than grammar is specificity. Compare:

Weak message Useful message
fix bug Fix rounding of totals below 1 euro
update Upgrade the date parsing library to 3.2
login changes Lock the account after five failed attempts
refactoring Extract shipping calculation into its own module

The body: explaining why

Not every commit needs a body. Fixing a typo in a comment requires no explanation. But when a change stems from a non-obvious decision, the body is the right place to tell the story:

  • what the problem was and how it showed up;
  • why you chose this solution and not a more obvious one;
  • what side effects or limits you know of;
  • useful references, such as the issue number in the tracking system.

Avoid instead restating the diff in words ("changed variable x to y on line 40"): Git already shows that.

Atomic commits

A good message is easy to write only if the commit has a single purpose. If you need to use "and" three times to describe it, it is probably three commits. Atomic commits bring practical advantages:

  1. Easier review: each change can be read and judged on its own.
  2. Precise undo: git revert removes exactly one change, without dragging anything else along.
  3. Effective bug hunting: git bisect, which finds the guilty commit by bisection, works much better with small, coherent commits.

The staging area helps a lot: with git add -p you can select individual hunks of changes from the same file and spread them across different commits.

Structured conventions

Some teams adopt formats such as Conventional Commits, where the subject starts with a type: feat:, fix:, docs:, refactor:. The advantage is that automated tools can generate release notes or decide the next version number by reading the history. The drawback is some rigidity. If your team uses it, follow it consistently; if you work alone, consider whether the benefit justifies the discipline it requires.

When to rewrite history

While developing on your own local branch, it is normal to make provisional commits. Before sharing them, you can reorder them and rewrite the messages with an interactive rebase, so the published history tells the story of the work cleanly. The rule not to break: do not rewrite commits already shared with others on common branches, because you would force everyone to realign their copies.

In short

  • The commit message is the only place to explain why the code changed.
  • Short, specific subject, blank line, optional body describing context and reasons.
  • Write the subject as a command and check that it completes "If applied, this commit will…".
  • One commit, one purpose: atomic commits simplify review, revert and bug hunting.
  • Tidy up local commits before sharing them, never ones already published.
MM
Marco Marzaduri

Marco Marzaduri works in cybersecurity, digital forensics and web development. With degrees in computer science and psychology, he combines technical analysis with an understanding of the human factor.

Read also