On commit messages
written on Thursday, April 2, 2026
Introduction
Writing good commit messages is not so easy, but clumsy commit messages can come bite you up in the future.
There are already many articles on this topic, but I wanted to write down my personal collection of tips and opinions on how to write better commit messages.
Explain why, not (just) what
A commit message has two main target audiences:
- At the time the code is written: the target audience is the reviewer or your code;
- 6 months later: the target audience is the person investigating a bug. This person can be, and will often be, you. So invest a bit of time now to make future-you happy :).
Commit messages should help both audiences answer the question: "Why did you make these changes?" The question is not: "What changes did you make?", they can answer this by looking at the diff itself. If the changes are large and can't be split into smaller commits, it can make sense to add a summary of them, but it should not be the only content of the commit message.
Even for smaller changes, the why can be important. Consider this one-line change to a list of dependencies:
dependencies=[
foo,
- bar
+ bar=1.2.3
]
A useless commit message would be:
Pin bar to 1.2.3
This does not bring any information, I can certainly infer from the diff that bar got pinned to 1.2.3. A more useful commit message would be:
Fix crash when computing bar
Pin bar to 1.2.3 because Bar.compute() crashes in 1.2.4.
External references
When relevant, include external references. The most common is a link of the issue from the issue tracker, or just the ID of the issue, but you can also include links to a chat discussion or a customer support ticket.
In our example, we can extend the previous commit message to include the ID from our issue tracker, and a link to Bar issue tracker:
Fix crash when computing bar
Pin bar to 1.2.3 because Bar.compute() crashes in 1.2.4.
See https://example.com/bar/issues/456.
Issue: 1234
Be careful about external references going away, though. For example do not include a link to a CI failure: the log will be gone soon. Instead, quote the relevant lines of the log in the message.
Description formatting
git itself does not enforce any formatting for the message description but nowadays it is common to use Markdown-like formatting for your content. I often use - for lists, ``` for code snippets, > for quotes and out-of-text links. Many tools can properly render text formatted this way, but thanks to Markdown, the content remains readable even in its raw form.
Many tools expect the lines in the description to be wrapped around 80 columns. It's a bit sad because I'd rather not bother with wrapping text when I am writing a long description, but that is the current status-quo, so don't forget to wrap those lines!
Make the title line relevant
Quoting git commit man page:
Though not required, it’s a good idea to begin the commit message with a single short (no more than 50 characters) line summarizing the change, followed by a blank line and then a more thorough description. The text up to the first blank line in a commit message is treated as the commit title, and that title is used throughout Git.
50 characters is really short. I personally find it hard to respect, especially if you use conventional commits (more on that below). I nevertheless keep my title line less than 80 characters long.
If the title line keeps getting too long, it usually means one of two things:
- Your title goes into too much details: some of it needs to go to the description.
- Your commit does too much and should be split. If you find yourself writing "AND" in your title line (as in: "Fix this and adjust that"), look back at your changes to see if they can be turned into one commit that does "Fix this" and another commit that does "Adjust that". Partial commits can help a lot. I wrote about how I do this with git gui (old but still relevant), but there are many other ways to split commits.
Conventional commits
More and more projects are switching to conventional commits. I personally don't like them much, for two reasons.
First, they lure you into thinking that you can then use your commit messages to generate changelogs. I consider this to be a mistake because nowadays changelogs are used as release notes, and release notes are for users of your project, whereas commit messages are for contributors to your project. I wrote more about this in a previous article.
Second, those prefixes waste valuable characters in the limited title line. The worse prefix IMHO is "fix". I often end up duplicating it because I write something like this:
fix(foo): fix crash when computing bar
On the other hand I find the optional scope (the part inside parenthesis) more useful: it helps when skimming commit messages in large repositories. If I am not forced to use conventional commits, I would write:
foo: fix crash when computing bar
Should a commit message always include a description?
Even if I am all for good commit descriptions, I don't think commit descriptions are mandatory.
A commit message should be as short as possible, but no shorter. If you come up with a commit title that explains the why with no ambiguity and does not need further explanations then I believe it's perfectly fine to stop there. Not all changes are complicated enough to warrant lengthy descriptions.
Comments vs commit messages
Sometimes one can wonder whether a piece of information should go in a code comment or in a commit message. I think it's OK to have a bit of redundancy here. But here are some observations I came up on this topic:
- Comments are easier to access and can be updated;
- Comments can get out of sync, commit messages cannot (at least once the commits have been merged into a permanent branch);
- Perhaps the most important: Comments are about the current state, commit messages are in the unique position where they can talk about before vs after. They are the right place to document the change, not just the end state.
Commits during reviews
When your code is going through review, you will often have to make changes. There are different schools of thought here, depending on the project culture and on what the tool used for reviews favors:
- Some projects expect you to rewrite your commits and force-push a new set of commits;
- Others want you to create new commits for changes requested during review and push them on top of the existing ones.
If your project prefers option 2, make sure to clean history before your changes are merged in the target branch. Squash these "review commits" into the original commits if necessary. Creating your review commits with git commit --fixup can help to squash them at the end.
What you don't want to see in the target branch are commits that look like that:
Take reviews into account
Every time I stumble upon such a commit message, I die a little inside because I know the content is going to be a mashup of unrelated issues.
On using AI to write commit messages
A common problem before AI was commit messages that were too terse (like "Fix bug"). AI flipped that: now we get hit by the opposite problem, overly long commit messages with little substance.
Blaise Pascal once said:
I made this one [letter] longer only because I have not had the leisure to make it shorter.
He probably did not have commit messages in mind, but his words apply just as well. If you allow AI to write commit messages, be sure to review and edit it. Trim it, remove Captain Obvious parts, useless information and overall make it read less like AI-generated text. Remember that commit messages are written once and read often.
Conclusion
That's all I have on this topic. I hope these tips help you overcome blank page anxiety when it's time to write a commit message.
If you only remember one thing from this article, let it be "Commit messages must explain WHY, not WHAT".