You Need to Write Meaningful Commit Messages
Your commits should tell a story for the future
I love a good book. Fiction or non-fiction. The books I enjoy the most usually tell some form of a story.
And most stories I know involve more than just a “beginning, middle, and end”. They usually involve chapters. Larger books use an even higher collection of chapters, breaking them into sections or even volumes.
The same is true for plays or musicals. The story is broken into acts, and then scenes. Part of this is to help the actors, but it also helps the audience. Interludes give a break to stretch your legs and use the restroom.
But more than anything, all of these elements help to logically group an idea or segment of a story to make it easier to understand. Because when you have help understanding the story, you can learn more about what the story is really about.
Source Control Tells a Story
Code is the same way. It tells a story. And like a story, your code needs chapters or markers to help understand it. There are many different types of chapter markers within code — packages, classes, etc.
However, code is also built over time. It wasn’t created in an instant. To understand why your code is built the way it is, you also need to understand the history of how it was built.
What decisions were made? Why is the naming between these classes so different? It would help to have something like a chapter to make it easier to answer those questions.
Thankfully, we have these things called source control systems that can help us tell that story. The chapter markers in most of these systems are called commits.
A commit is essentially a set of changes with the same theme that are made to the codebase. It usually has a brief message describing why the change was made.
Unfortunately, these messages tend to be, well, unhelpful. When was the last time you read commit messages that looked like the following?
Fixed some testsRefactoringChanges per code reviewok - now it's done...
How unhelpful is that? What tests were fixed? Were they broken before? Or was it TDD that wasn’t done? What were you refactoring? What is the “it” that is now “done”?
If I am attempting to understand the story of these changes, those messages don’t tell me a whole lot.
Ideally, the would give me some insight into the intention of the change. Why it was needed (i.e. a story or bug). Who requested the change. That is really what I want to know when I am looking through a Git log.
What Is a Meaningful Message?
However, super-detailed messages can be just as frustrating. Messages that enumerate every file you have changed will quickly become glossed over.
Also, in most source-control systems, enumerating every change is redundant. The system can tell you the specifics if you need to see them.
There are a lot of good articles on this from other great writers. They all differ a little bit in terms of format and the actual content of commit messages (more on that below), but they all agree on a few core pieces.
1. Separate subject vs. body
This is more crucial than you might think.
Why? Well, it’s like an email. If you’re scanning through your email history, you aren’t going to read the whole message. Instead, you want a quick blurb that summarizes the content.
This especially true if you are using commands like
git log --oneline or
The detailed part is also important, but it won’t be the first thing you see in the logs. Like comments, this might be a good place to point out additional notes about the specifics or the whys of a change.
For instance, if you had to do a refactoring commit before making a feature change, this would be a good place to say so. Or, if you had to make changes that had to take into account some edge case or something, the body is the perfect place to add it.
2. Keep the subject line succinct and unambiguous
Git itself recommends keeping characters less than 50, but other guides say somewhere less than 72. At any rate — keep it succinct. Not being able to describe a commit that short probably means your commit is too big…
In addition to being short and readable, subject messages should be unambiguous about the change. It should describe what will happen to your codebase if you apply the change.
This is the same idea as “clean code” functions. Each function does basically what it says it will do. Likewise, a meaningful commit will do exactly what its commit message says it would.
Your message should also be in the imperative active voice.
Don’t use phrases like “fixed the bug in the time flux capacitor” or “changing the target date to Nov 5, 1955”. Instead, say “fix to the flux capacitor to require less plutonium” or “set the target travel date to Nov 5, 1955”.
The way this GitHub gist describes the commit message is really good:
“A properly formed git commit subject line should always be able to complete the following sentence:
If applied, this commit will <your subject line here>.”
Boom. If every commit acted that way, how much easier would history tracking be? How much easier would code reviews be?
3. Have a consistent format
Formatting is just one of those things you can’t get away from. Consistent formatting always makes a repository easier to work with. It largely applies to code though, so applying it to a Git might seem silly.
It’s not silly though, it’s necessary.
When you are reading a book, you have already agreed on a format style once you buy it and start reading. If the publisher decided that they would allow some lines to be shorter or longer than others, you would have a much harder time reading it.
The same applies to your commit messages (and your code!). When the format is consistent, understanding can be at its highest.
The important thing is for your team to pick and stick with a style of their own. If you’re working in open source, make sure you follow the standards for the repositories you contribute to.
4. Meaningful messages come from meaningful changes
None of this matters if you have commits that don’t do anything. Or do too much. Or are half-baked and broken.
Think about your commits as an atomic transaction. At the end of every commit, you would ideally have a working codebase. At the very least it should be compilable.
You want to have added some value without having broken something (at least intentionally — we will always make mistakes).
The benefit here is that if you made a mistake and broke something, you can revert just that one commit to get back to a working state. And this might be the reason that “squash and merge” is how my team merges pull requests…
All of this is to say that if you focus on first making small, meaningful changes and committing incrementally, it will be easier to do all of the other items.
To put those rules into a simple bulleted list, it looks like:
- Separate subject and body.
- Keep the subject line short and unambiguous.
- Have a consistent format.
- Meaningful, atomic commits.
Now that we have covered some of that, here are some examples of meaningful commit messages.
Note, these are all made up, but they should serve as some examples across different formats and guidelines. While they aren’t consistent with each other, you can figure out the convention for each with a little thought.
SYS-1345 (docs) - update method of procedure for upgrading hypervisorThe documentation for upgrading hypervisors was out of dateBug (api) : fix to response code returned in case of internal timeout (#API-4588)Our API was returning a 400 bad request when an internal timeout occurred. This change makes that response code a 503 to tell the client the request is retryableFeature #99 : allow users to re-arrange their dashboardThis change finally implements the ability for users to re-arrange their home dashboard via drag-n-drop. Some notes:
- currently toggleable. we will wait until an announcement is made to turn the toggle on
- drag-n-drop is limited only to dashboards already created. still need to implement drag-n-drop of a widget "template". this is capture in feature #100