Six months from now, someone will point a tool at a single line of code and ask: why is this here? The answer lives in the commit that introduced it — if that commit said anything useful. A message of "fix", "update" or "changes" answers nothing, and the trail goes cold exactly when you need it most.

Good commit messages are not ceremony. They are the cheapest documentation you will ever write, produced at the one moment you fully understand the change: right after making it.

Explain the why, not the what

The diff already shows what changed — which lines, which files. What it cannot show is why. A message that says "increase timeout to 30s because the export endpoint is slow for large accounts" tells a future reader something the code never could: the reason, the constraint, the trade-off. That context is what makes a change safe to modify later.

A useful default shape is a short summary line under about fifty characters, written as an instruction ("Add retry to upload"), followed by a blank line and a paragraph of reasoning when the change is not obvious. Trivial changes need only the summary; subtle ones deserve the paragraph.

One logical change per commit

A commit that bundles a bug fix, a rename and a new feature is impossible to describe honestly and impossible to revert cleanly. Keeping each commit to one logical change makes the history readable, makes reverting a single mistake possible, and makes review far easier because each step has one intention.

This does not mean tiny commits for their own sake; it means each commit should be a coherent unit you could describe in one sentence without an "and". If your summary needs an "and", it is probably two commits.

History is a feature, not exhaust

Treated well, the commit log becomes a searchable record of every decision the codebase ever made — why a workaround exists, when a bug was introduced, what a confusing function is actually for. Tools that trace a line back to its origin turn that record into instant answers, but only if the messages held real information.

The habit costs a few extra seconds per commit and repays them many times over the first time a production incident sends you spelunking through history at speed. Write for the tired person debugging at midnight. It will often be you.