Rethinking our commit messages structure.
If you are working in a company, in a team or also alone, probably you are using also an issue/project tracker like JIRA or the ones included in GitHub, GitLab and Bitbucket.
The advantage of those pieces of software is that we can create “issues” or “tickets”, each of those tracking development of a single feature or bug correction in our software.
They work by creating and assigning an ID to the newly created ticket — that can be numeric or include a brief project identifier like ALX-1231 — in the way you can keep each one easily referenceable in chats, groups, commits, etc.
Commits, commits, commits
If we have used Git at least one time, we would know that the standard commit message structure is:
Commit summary description; corrected my horrible bug
Long description (sometimes called "body"), with things like:
* bulleted list of changes;
* other change;
* chirp chirp
Notice the new line between the summary and the body: Git doesn’t enforce it, but we have to insert it if we want to specify a body, else the commit will not be parsed in the correct way.
Many teams have a default way to reference tickets created with tracking software, putting the issue ID inside the commit message itself.
The standard I saw more frequently is something like this:
ALX-21313 Done that fancy change; now we have cats in the UI
Seems good, probably you are using it in your dev workflow. But I want to talk about why I think this structure is not the best one to use.
1. Using the issue ID as first-class citizen into our commit message is not the best thing to do.
We have Git, and then we have a separate system that manages issues.
One day in the future the latter could stop working, be abandoned, its database could be deleted as a mistake, or everything else. In that moment, we will realise that our Git messages will have a consistent part that has no more meaning. Issue trackers are not part of the Git repo.
2. The issue ID is wasting precious space that instead could be used to explain what we’ve done in that commit.
Commit summaries should have less than 50 characters. Appending 6/7 characters for the issue ID means that we’ll have 6/7 — but maybe more — less characters to use for describing what changes were made.
Yes: we could write the full text into the description, but probably we could have used those 7 chars for fitting those in the summary and then write the issue ID in the description (spoiler to my solution at the end of the article).
Apart from this, in my experience I found that developers that uses IDs before the “real” commit message, tend to be lazy about what to write in the summary, because they are psychologically prone to the fact that who’s going to read the message, will check the ticket itself for more details. This will take time from him; time otherwise used for being productive. This without quoting the possibility that the issue manager itself could be not accessible temporarily or indefinitely.
3. The linked issue’s nature and its state after the commit is not clear.
An issue can have different types. It can be a bug, a new feature, etc.
If we just put its ID in front of the message, who will check our project’s logs won’t know if that commit will fix, close or just reference that particular ticket. For more info, again, he has to go to the issue manager, breaking its workflow.
4. What about many issues? And no issues at all?
Let’s say that our commit fixes three tickets, because those were very similar (sometimes is possible that QAs create different issues, without knowing that they are caused by the same bug in the code).
We’ll have something like
ALX-12323 ALX-12324 ALX-12325 Something fixed finally
Isn’t that ugly?
And what about the opposite? When we are making a subtle change like correcting a typo in a comment. We can’t create a ticket just for correcting a word in an insignificant comment (we could but I think it feels quite paranoid).
So we’ll have a commit message without an initial commit, resulting quite incoherent respect to the other commit messages.
The approach I suggest
If I convinced you with the previous points that the most used format is not so useful and perfect, now I’m going to explain my favourite approach to Git messages.
The first thing we are going to do is to explain the code changes in a summarily way. Don’t look at the issue/ticket! Just look at your changes and describe briefly what we changed in overall.
Renamed MyUglyTweet to MyBeautifulTweet
If we have made many changes in this commit, describe the main purpose of those changes, and then we’ll continue to explain it in the commit body (if needed):
Added little birbs to the homescreen
* Updated BIRDS_NUMBER constant;
* created the interface Chirp and implemented in ChirpImpl;
“Ok Alex, but when should we put our issue IDs?”
Once we have finished to summarize every block of changes we made, let’s decide where to put our ticket identifiers.
If our commit contains changes regarding just one ticket, I follow this path: if there’s enough space in the summary, I append the issue preceded by a verb that will describe how that’s related. For example:
Added little birbs to the homescreen; closes ALX-1434
We can use closes, closed, close, as soon that verb identifies what we’ve done on that ticket. I use close for feature tickets, but in the case of a bug ticket, I usually use “fixes” or “fixed”.
For these verbs, or keywords, we can check here https://help.github.com/articles/closing-issues-using-keywords/, because specifying those in the commit helps some issue trackers (like the GitHub one) to close automatically our tickets when a feature branch is merged with our main development branch.
If there’s no space left in the summary, we can put the ticket on the description:
Added little birbs to the homescreen, bla bla bla boring
Or, if we have a list of things changed (but our commit closes only one ticket), we can put the issue in a separate list item:
Added little birbs to the homescreen, bla bla bla boring
* Created new classes;
* injected cream in the blender;
* closes ALX-1434
In case we have more issues closed by our commit, we’ll try to have one element of the list for each issue closed:
Refactored code bla bla bla bla here's no space to write anything
* Extracted interface from the Qwack class (closes ALX-1323);
* cut wings to Para.kt :bird: (fixes ALX-1324);
* this other change doesn't close anything :pensive:
I think this approach is quite simple but very effective for including our tickets in the commits without sacrificing the importance to write a commit message that can be read without the issue tracker opened on our browser (and with a proper integration, we can leave our automations to move tickets as we do certain actions, but I’ll leave this to another article).
If you enjoyed reading this article, feel free to click the 👏 button how many times you want!
Extra chapter: do you know that you can use emoji in your commit messages? 😁
Maybe you’ve noticed that I used
:pensive: in my last example commit message. That’s a word enclosed by two colons (the punctuation symbol, not the intestine part…) that will be converted from many Git services to real emoji! GitHub, Bitbucket and GitLab all have support for this feature.
All the emoji with relative code are on websites like https://emoji.muan.co/.
Git commits don’t need to be boring, but remember: be responsible and use your emoji in your description, or in your summary only if you are really sure that you have enough space, and more important don’t use emoji for explaining stuff, because who’s reading that commit message could be using the terminal! 😉