How to remove unnecessary friction with good commit messages
How do you feel about commit messages like “Fixing a bug”?
I, personally, don’t feel great. Part of me feels guilty - as I sure did it in the past, and part of me feels sad, as it reminds me about time I lost and will never be able to get back. While I learned the lesson, I keep seeing diffs with unhelpful messages that, once committed, may cause unnecessary drama in the future.
Why good commit messages matter?
Clarity
The act of writing a commit message forces you to think about your changes. While doing this, you may realize you missed handling a corner case or didn’t add tests. Having a hard time writing a good commit message may indicate your change is not ready for review - maybe it’s too big and needs to be split or maybe it’s not even needed.Historical context
Software archeology is daunting. You are looking at some ancient code wondering what it does, if it is needed, why it is needed and why it looks like this. A good commit message can quickly answer all these questions. (Funnily, checking the commit details will often reveal you wrote this code).Code review context
Good commit messages can facilitate faster code reviews. They tell potential reviewers what they are signing up for and eliminate the effort needed to deduce the main idea from the code.Searchability
Looking at older commits is a not an uncommon task. But before you can look at them you need to find them. Good commit messages make finding commits easy.
How to write a good commit message?
Making a commit message long does not make it a good commit message. Good commit messages are short but informative. For some code changes a one-line commit message is perfectly fine. Other may need more details. Here is what I consider when writing a commit message:
What exactly the change is about. This information is mandatory for each commit, and it should be always included in the title.
Why I am making this change. What scenario it unblocks. What issue it fixes.
Short description of implementation details.
If fixing a bug, how to reproduce it.
How I tested the change - especially useful for any validation beyond unit tests. (This one is super interesting - sometimes I notice my validation found an issue only when providing validation details in the commit message).
Links to related issues, tasks and commits.
Examples
Here are a couple commit messages from one of my open source projects - the Swift SignalR Client.
Commit 75412e9
Bump SignalRClientSwift to 1.0.0
This is an example where a one-line commit message is sufficient. I don’t need to open the code to know that this commit increases the version of the SignalRClientSwift
library to version “1.0.0”. Even though the code makes it obvious, the description is still useful because this project has multiple dependencies (e.g. npm packages, NuGet packages, .NET Core) that are also occasionally updated so I immediately know which one of them was updated.
Commit 0e7a67e
Fix a regression that results in a deadlock
This refactoring f4558f6 effectively removed the fix introduced in #244 and the client started deadlocking if a keep alive was sent during reconnects. To avoid deadlocks the callback will be now scheduled asynchronously on the callback queue if there is an error due to a reconnect. For all other cases ReconnectableConnection will rely on the fact that the underling HttpConnection already schedules callbacks to be
executed asynchronously.
Fixes: #264
In this example the title points that the change is fixing a deadlock which is is a regression. The description gives more details, including how the regression was introduced and how to reproduce it. Then it discusses the fix and explains why the fix is needed in only one place. There is nothing about testing as this project only relies on tests, which were updated.
Conclusion
Writing good commit messages doesn’t take a lot of time but can save you and your team members a lot of time.
Thanks for reading,
- Pawel