The secret to great commit messages
And why crafting good commit messages is an investment worth making regularly.
Much has already been said about commit messages, and the consensus seems to follow the seven rules of great commit messages that Chris Beams outlines:
- Separate subject from body with a blank line
- Limit the subject line to 50 characters
- Capitalize the subject line
- Do not end the subject line with a period
- Use the imperative mood in the subject line
- Wrap the body at 72 characters
- Use the body to explain what and why vs. how
I see two main categories. Rules 1–6 might be summarized as: “Use good formatting”. This is the minimum bar for any quality commit message, and is something that any developer should be able to learn and apply in a few minutes and enforce with a linter. Commit messages should be well-formed. This part is easy. You may have seen Tim Pope’s model commit message. Learn it, live it, love it—it’s good:
Rule 7 “Use the body to explain what and why vs. how”, on the other hand, is special—it deals with the content of the commit message, not the formatting.
The why is the secret behind the best commit messages, and that deserves special attention.
I try to be mindful that commit messages are for two audiences: code reviewers and future developers (including myself). I aim at giving these audiences context to understand why I made the decisions I made, which will help them make better decisions about the code I am committing today. My investment in writing high-quality commit messages pays increasing dividends as my team changes or as I forget things, and is well worth the time and effort.
Software development is a constant exercise in picking from a set of tradeoffs. When modifying a piece of code, knowing the tradeoffs at play can save time and effort, resulting in higher quality software. Pulling this context together by just looking at the code is very difficult. The commit message is the perfect place to encapsulate this information, and makes it available to others via tools like git blame.
I make sure to discuss any difficulties that were encountered along the way—that information may help future developers who run into similar problems with my code.
Great commit messages will explain other approaches that were considered, where appropriate, and discuss the advantages and disadvantages of each approach. Although this helps get your commit through code review it also gives future developers more context to make informed decisions about changes to the code.
While one-liners should be relatively rare—there is usually some useful context to communicate, such as my motivation for making the change—I also try to be careful to not write overly-verbose commit messages. At Brigade, we use overcommit to manage our git commit hooks. This tool has an easter egg that congratulates me if I composed a long commit message. While this is a bit of fun, a highly detailed description of exactly what was changed isn’t actually very useful since that is captured in the diff. Write too much and run the risk of it not being read.
If my commit message gets too long or difficult to write, my commit might be too big. I take this cue to go back and see if I can break it into smaller, atomic commits. Especially when I am working in a collaborative environment, I’ve found that these smaller commits are easier to review, merge quickly, and rebase cleanly — helping my team ship faster.
Incidental changes that aren’t the main purpose of the commit, such as fixing some whitespace on a nearby line, should ideally be in their own commits. However, separating these out is sometimes more trouble than it’s worth, so I often take the pragmatic route and just mention them in the commit message to help people understand why it was done.
If I am fixing a bug or deleting some dead code, I mention relevant commits by hash. This helps build a narrative and closes the loop, making git spelunkers’ lives a little easier.
Likewise, the best commit messages will contain URLs with more information. For example, if I borrowed a solution from a Stack Overflow answer, I include its URL in my commit message (along with a comment in my code). Or, if I fixed a bug related to an error message that was logged in a system like Sentry or Airbrake, I include a link to the error. If my commit relates to something stored in an issue tracker somewhere, I include a reference to that issue. This will help people find more context. At Brigade, we like to write these links like Markdown endnote style, but any way is fine:
Write a concise and descriptive subject
This is the body of my commit message, which is embedded in
a post on Medium by @lencioni [0].
[0]: https://medium.com/@lencioni
Most problems have multiple possible solutions. Writing down why I want to solve a problem in a particular way forces me to reflect and think deeply about why I did that piece of work, and this puts me in a better mindset to create better solutions in the first place.
It is also worthwhile to take pride in honing the craft of software development. This means that I write my commit messages with proper punctuation, spelling, and grammar. If you are using Vim, you can turn on spellcheck for git commit messages by adding the following configuration:
autocmd BufNewFile,BufRead COMMIT_EDITMSG setlocal spell
And, to make Vim use smart auto-indenting inside numbered lists:
formatoptions += n
Finally, commit messages are a communication tool that can help set the tone for my team. This is especially important when working with a distributed team where face-to-face communication is more difficult.
In summary, if you:
- properly format your commit messages
- explain the what and why of the change
- discuss any difficulties or tradeoffs made
- mention alternative solutions considered
- reference any relevant commits or online resources
your team and future self will thank you, and your investment will pay back dividends in speed, quality, and productivity.