Why Your Should Keep Project Management out of Your Commit Titles

It is pretty usual to prefix the commit titles in your repository with the ticket number of what this issue resolves. Something like this:

A rather long Git commit title in Github

I would like to make a compelling case for why this is not a very good idea to begin with, with one small exception.

As we know, Git commit messages have pretty strict guidelines on how they should be formatted. The guidelines are well known, and just to recap: a Git commit message consists of a commit title - hard-limited in display to 50 characters - and of the commit message body.

Even though the commit title size is arbitrarily chosen - for reasons such as using it in an email subject line when generating a patch - the fact that we are using Git and are about to be using Git for the foreseeable future means that this is a hard limit. And it does have consequences. Long commit titles are not pleasant to deal with. They have rather ugly overflow in Github:

and they get very long in Git commandline display:

$ git log --pretty=oneline
a4b4f44 (HEAD -> git-commit-titles, origin/git-commit-titles) DJYRA-745 feat/task: Modify shlobulator to explicate the conflagrator. We need to derezz the flux core for this.
0eef372 (origin/master, origin/HEAD, master) Fix image scaling on mobile
5233646 Customise the feed URL

And here is the rub: 50 characters is very little. It is less than the 140 characters you get on Twitter for example. And most tools you are going to be using are going to be truncating to this length by default. For example, GitX:

GitX truncating the commit title at 50 characters

Of those 50 characters, the standard pattern of 4JRA-1234 consumes 9 characters (if you count the space after it). Almost a fifth of the useful information you can provide to the reader. And where the reader is involved, we get to the purpose of those commit messages.

They are meant to communicate something to the person who is going to be looking for a possible defect or a change that you have introduced. Possibly years after your work is complete. When you cram your JIRA ticket numbers in there, you waste the space in the commit title which is at a high premium - to imprint your project management methodology du jour into the project. And it gets way less neat because of this simple maxim:

Trends in project managment tools change. Code stays.

A codebase can outlive a number of different project management tools throughout its lifetime. I am working on a codebase that has survived, in no particular order:

Once a codebase (and a software project, or a software team) switches tools, in every single one of those cases the “previous” project management tool ended up being discarded and projects closed. It is no longer possible to find A485, and no longer possible to find T523 either, even though they stand front and center at the start of every single commit. When dealing with defects or incidents it actually becomes a problem - because exactly when the information about the what of a particular change is the moste direly needed - what the reader finds instead is a runic image of a project management tool this person has never seen. And can no longer consult.

Moreover - three of these were “off-repo” numbers. By “off-repo” I mean that they were numbers assigned to things which were not integrated with the source management solution in use at the time. To extract any and all possible use from these, you would need to install a browser extension or an SCM plugin which would make these numbers clickable, so congratulations - you also just added another step to your onboarding procedure if you want to cover that.

And once these numbers really go up (may your software project have a long and prosperous history!) these numbers start eating into your commit titles - big time.

Github and Gitlab form a good exception to this rule - they hyperlink the pull/merge request at the end of the merge commit title because within the system hosting the code this reference (the #123) is clickable by default. And since it is clickable by default this is the only issue/ticket reference you should tolerate in your commit titles – everyone onboarded onto your code hosting system fo choice already knows how to use it.

Semantic commits are also not that great

Semantic commits also want to bite away a piece of your 50 characters, with prefixes like:

chore: Update libswap to 0.4.2
feat: Modernize the user card view

The reason why semantic commits have the same issue as the issues is that they capture transient intent - or, to be more sharp - your opinion on project management strategy that is anchored in time within a resource that is much more persistent than the said opinion. What you consider a Task today might as well become a Feature tomorrow when the backlog grooming reprioritizes your user story. What today is a chore might actually be a feature significant upgrade of an important component you are using all over the place.

Aside - chore as a word strikes me as odd because one could just as well put shitwork: Apply critical security update to libwebserver 4.0 to the same effect. Taking care of your code is not a chore, it is something that we should be doing with respect and dignity. You usually need that libwebserver up-to-date.

In other words: semantic commits imprint a limited, managerial perspective on software project management into commit titles, and there is a chance this limited view is not going to age well or reflect the actual impact of the change.

There is arguing that those chore: prefixes can disclose why a certain change was applied, but hear me out on this one. Imagine a hypothetical SRE diagnosing an issue in your application. They see a list of commits like this:

chore: Update libdarkwater to 0.4.1
chore: Update libdarkwater to 0.4.0
feat: Ensure resolution interpolation is off for images smaller than 1024px

These so-called “semantic prefixes” tell you very little - they tell you what the person committing the changes though their changes were from the perspective of the project management and impact. To demonstrate, let’s see what happens if we remove the “meat” of the commit titles and only leave those labels:

chore:
chore:
feat:

This does not fullfill the most important purpose of code and its metadata - it does not communicate intent, the “why” of the change. The most the SRE will be able to deduce from them is “so the developer proooobably thought that this was just a dependency update?…” but this is not guaranteed at all.

Here is what is important instead: “Which of these commits introduced an issue?” The semantic commits do not communicate this one bit. They also do not stand their ground in the case of feature domino failures (if the resolution interpolation specifically in combination with libdarkwater 0.4.0 causes all the images to become pink, for example).

If we remove the semantic commit prefixes:

Update libdarkwater to 0.4.1
Update libdarkwater to 0.4.0
Ensure resolution interpolation is off for images smaller than 1024px

the useful information still ends up being retained. Tip: - if you se a modern dependency update service such as dependabot or Depfu you will be able to see the icon of the service in Github, which will conveniently replace the commit title bits.

What you really want instead

Both issue numbers in titles and the attempts at “classifying creative work” in semantic commits actually try to do very similar things. They try to point (issue numbers) or try to explain inline (semantic commits) the reason why a change was applied. And there is a great tool for that which already exists - it is writing good prose. The commit body has all the requisite space for you to

Do your reader a favor - write prose instead, and take time to explain as much of the why as you possibly can. With all the issue numbers - and even better - URLs - without having your reader investigate “what was this weirdo XYZ issue tracker they were using back then?”