A wide majority of developers uses a version control system for their code and many of them trust in git. This is good, but most of you will for sure be familiar with the following situation:
During the investigation of bugfix, you were able to nail it down to a block, function or line of code, but the rational behind the code isn’t obvious. Thank god there is “git blame”, but sadly you end up by a message like “Doing foo” or “Adapting comments from PR”.
This is really frustrating, because you cannot judge if the change was intended to have the current behaviour or it has the behaviour by accident. To overcome this shortcomings, the following guidelines proved in my daily work to support such things. Nevertheless, it requires self-discipline to stick to them. Therefore, they should also be part of the review.
There are plenty of other guides for writing good commits out there, but the following rules were the essence from them that worked for me.
Why commit messages matter
- Commits document the evolution of the code
- Highlights the reasoning behind the changes
- Creates context during bugfixing
- Contains helpfull metadata that supports automation
The anatomy of a git commit message
Before we start discussing good commits messages, we need to have a closer look to a commit message as they are structured in several sections in git.
This is the subject
The body contains some more information about the changes in this commit.
Some-Metadata: Lorem ipsum
Let’s take a closer look at the commit message
The first line contains the subject of the commit and is followed by a blank line. The blank line separates the subject from the body. After another blank line at the end is in the footer space for additional metadata.
Guidelines
The subject shall not exceed 50 characters.
Reason: Most of the UIs uses the subject in the logview and the content is truncated after 50 characters. As this limit varies from UI to UI, the absolute number might need to be adapted to your environment.
The subject should be in imperative mood
Reason: Git uses for the commit it creates itself the imperative mood and by adapting that style the log stays consistent.
Merge branch feature-abc
Revert "Commit subject"
This reverts commit <commit-hash>
The subject shall start with a capital letter
Reason: The subject is the heading of your commit and furthermore, the only content shown in condensed views. Additionally, git capitalizes its messages as well. By again adapting this style, your log keeps a consistent look and feel.
The subject should not end with a punctuation mark
Reason: The subject can be treated as a heading and due to the limited space key to success is to omit every unnecessary characater.
The subject shall summarize the change
Reason: The subject is the only information in condensed views, such as ˋgit blameˋ or ˋgit log –onelineˋ that is available. Therefore, a condensed meaningful description helps to understand the history.
One line in the body shall not exceed 72 characters
Reason: To ensure a good readability across as many UIs as possible the body shall not exceed the 72 characters. This limit is far more fuzzy than the subject line and should also be adapted regarding the actual environment.
The body should explain why the changes were made
Reason: What was changed can be get from the diff, but for understanding the changes it is essential to know why the changes were made. After some weeks often the author itselft isn’t aware why these changes has to be done. Referring to the issue in the ticket system is not sufficient, as this might become unavailable at the time the information is needed. Nonetheless, it is good practice to mention the issue tackled by the commit. But this should be done in the footer.
The body shall motivate the rational behind the changes
Reason: The git log is the history of your changes and the evolution of the code itself could easily be gathered from the history, but the change does not tell, why it was made. Therefore, it helps the next developer, even if it’s just your future self, to understand the change and the context why it was made. This helps to verify, if a behaviour was intended or just a mistake. Furthermore, the rational behind changes supports the understanding of the change itself. This speeds up bugfixing and incorporation with the code.
Discussion: At the time of writing multiple AI assistants offers support for writing a commit message (e.g. GitHub Copilot), but during my tests they fail to add the rational behind changes. They are good in describing what was changed, but as the intention is mostly not obvious from the change, they could not come up with a message, that satisfies me. But if you if have good commit messages, they may be able to provide a viable first version for a pull request.
The metadata shall be added as a git-trailer
A git-trailer is a structured metadata within a commit message in the form of a key value pair in the footer of a commit message. It's used by git itself, for example if you use the "--sign-off" option.
Trailer can either be added manually by adding "<key>: <value>" at the bottom of the message or by using the "--trailer" option. They can be parsed with "git-interpret-trailers".
For a more detailed description please have a look at https://alchemists.io/articles/git_trailers or the git reference.
Reason: Adding the metadata as git-trailer makes it available for automated tasks. This eases the generation of changelogs, automated transition of issues.
Discussion: A common approach is to add the issue id to the title. On the one hand this has the benefit of visibility in the log, but on the other hand it further decreases the available characters for the title, if you follow the above guideline. Especially, if one commit addresses multiple issues this preamble could be very lengthy. The same argumentation applies from my point of view to conventional commits. I really appreciate the underlying idea of categorizing the the commits, as this leads to more cohesion in a diff, but by adding the category and a (optional) scope, this limits the remaining space for the title.
Conclusion
Writing good commit messages is as hard as writing useful documentation, but both will help you and others to understand the code much faster and with less pain. Furthermore, it will speed up your bug fixing as a good commit message provides informations far beyond the change and provides a context to the change.
If you struggle writing a subject within the limitations this might be caused by putting to many changes into one commit and it should be split up, but this is another story and will be covered in a future post.
Leave a Reply