Why I still hand write my commit messages

For over a decade, I've been a proponent of writing detailed Git commit messages. I find it a valuable use of my time, and continue to double down on it, even in a world where you can get a Large Language Model (LLM) to write it for you.
In the past, I've written about at least 89 strong feelings I have about Git commits, so I'm naturally biased to the benefit of commit messages, but why does this still hold in the current age, where a lot of people are delegating that to an AI agent, if at all?
"Why" is better than "what"
One of the most important things a commit message should explain is why you're making a given change.
Chris Beams' post about writing commit messages is probably one of the more cited blog posts of all time, and is a great resource on this and a number of other important pieces to remember when writing a commit message.
Unfortunately a lot of humans, and by extension LLMs, still continue to re-explain what has changed in a given commit. Generally, the "what" is clear, as you can see it in the diff itself. Although not all code is "self-documenting", you can generally see "what" is changed by looking at a commit's diff.
If you don't document why you're making the change, you're missing out on really important context.
Some other areas I focus on calling out:
- if this is a prerequisite/prefactor for other changes
- if this is a bug that this fix is resolving (not only referencing issues/JIRA tickets, but also any examples or error messages of note)
- whether this has crept in due to a gap in my own review/implementation
- it's only a blame culture when it's me, otherwise I'll use
we- i.e.I'd missed this from $sha
- it's only a blame culture when it's me, otherwise I'll use
- if there were any trade-offs, such as why we're executing an external command, instead of implementing a Typescript-based parser
In each of these cases, it helps provide more insight into what led to the change and why we're doing it.
Can I explain it?
The process of writing the commit message is also greatly helpful in determining whether I do actually understand the changes I've just made.
As we heard last week at GopherCon UK, a study in 2014 shows that you are more likely to retain knowledge if you are expected to teach it.
By making sure that I need to explain why a given commit's changes are necessary, I can make sure I do actually understand what I'm about to commit, and how I'd explain it in my own words.
I'll very often find that - even with changes I've fully authored myself - as I'm going to explain it, I don't necessarily agree with a choice I've made, or now that I've stepped back to review the changes, I can see a better option.
I've found this to be a positive experience when writing documentation in the past, too. When you're trying to explain a new feature, or clarify existing functionality, you often need to "take a step back" and rethink how a user who may be unfamiliar with the inner workings of the project will reason about it, and by doing that, you may find that there's a lot of implied understanding you need to break through.
When working through my commit messages, I'll watch out for occurrences of Also, ... or Additionally, ... - sometimes they're OK, but it's often a case of a commit that is trying to do too much, which requires breaking down the changes into multiple commits.
I'm the author now
In the case I'm working with some AI-assisted code, I may not have necessarily been the driver of the changes or making a lot of the decisions that were made.
By having to explain the choices in the commit message, I'm not only working out why the decisions were made, but taking full ownership of the changes.
(regardless of whether you do this or not, if you've committed it, it's your responsibility!)
Indicating what specific areas are AI assisted
I work to introduce atomic commits where possible, which allows me to add per-commit attribution for AI usage.
In cases where I am using AI to support a change, I can opt to specify in the commit message exactly what pieces have had AI assistance, allowing a way to call out specific areas the different AI model(s) have been used.
AI can't replicate my taste (yet?)
Last week, I'd been working on some personal projects that I've been struggling to make the time to work on, so decided to get my Claude for Open Source (Claude Max) subscription to work.
I decided to vibe it a little, and allow Claude to commit atomically as it needed to. I don't particularly like the way it writes its commits, so I put Claude Fable on the task of taking 100 of my most recent commits and creating a skill for committing as me to improve the resulting commits.
It wasn't surprising that these commits were better, but not quite my writing style. That's absolutely OK - I don't actually want an AI to be able to write like I do.
But it is a nice point where in projects I'm not as bothered about writing the perfect commit message, I can get something reasonable that sounds a bit more like what I'd want out of it.
In projects where I do want to write the commits, having a starting point can be useful, too.
I enjoy documenting
I've had an affinity for writing documentation for some time. Some of it is down to my familiarity with writing as a form of blogumentation, how it helps my neurodiverse brain, but also because I see a tonne of value from better documentation.
I'm definitely not as skilled as a Technical Writer™️, but I've found over the years that between my better writing skills than many of my colleagues, and have a strong empathy for my users, that I'll end up doing more of the documentation-oriented pieces of work.
Naturally, writing commit messages leans into this, as it's another important piece of documentation.
I'm not forcing you
To be very clear, this is how I work and how I want to handle this myself.
Even in the projects I run, I don't enforce this on anyone - I've learned over the years it's not worth it to try and require it - and although I'm happy spending the time doing it, not everyone is as interested.
I find it to be a valuable process, and helps me work through the thinking behind a change.
But that doesn't mean I'm even "forcing" myself to do this - writing can be quite brain intensive, and so sometimes I don't have the capacity to do it.
Examples
Want some worked examples?
- ci: don't allow breaking changes in PR commit messages (with a mini-postmortem of an incident)
- fix(datasource/pypi): use the earliest
upload_timeof a version - Three commits in a common area, reducing overload on Maven Central:
- fix: correctly warn when an attestation is missing (as a security-conscious change)
- ci(tools/json-schema): validate JSON schemas are well-formed (AI model attribution)