Improving Your Change Logs - The bluejava Git Commit Message Format

August 6, 2015

In this article I make the case for following a guide or specification when entering Git commit messages. I then propose a guide that I have put together and published on Github at https://github.com/bluejava/git-commit-guide

"There is nothing permanent except change." – Heraclitus

Git-ing things done

So, you and your team manage your code changes with Git. Great! But what commit message format has your team adopted? None? A tacit agreement to "be clear and concise"? Or do you have an actual written and specified format that you all conform to?

I have been using Git for some time - and have always strived to be a good Git citizen (A good gitizen if you will… or maybe you won't…) - using short descriptive messages, atomic commits, etc. But admittedly, I had no standard or guide that I followed. Different commits sometimes used different grammatical moods ("added" vs. "adding" vs. "add") or even different words ("added" vs. "built" vs "enhanced") to refer to the same type of change.

A quick review of popular GitHub repositories reveals that most developers have a similar approach. Here are some commit messages from some popular repositories:

These kinds of change log entries are not very useful. They mostly act as "placeholders" for a dated change - and information about the nature of the change or why it was made is unclear; or must be deduced by looking at the "diff". (Not to pick on these developers or these projects - I also am guilty of these kinds of log entries - hence this endeavor!)

The benefits of a consistent and informative change log message are wide ranging - starting with making it much easier to visually scan down commits list and find changes relevant to your search. Additionally, following a specific format opens the door to grep'ing and extracting useful information from your change logs programmatically.

It's a real productivity gain to use your commit logs to:

  • List out all new features since your last release
  • Locate bug introductions faster by skipping non-code changes in your git bisect runs
  • List out changes to a particular subsystem
  • Review the impact of a feature (wrt bugs, etc)
  • Answer many other questions regarding your changes over time

For large projects and/or teams this could result in huge time savings. And for smaller projects, its another opportunity to realize those cumulative benefits from multiple small improvements!

The Search For Best Practices

So I did some poking around and found some guides from the Atom Organization, Typo3, one derived from AngularJS by Stephen Parish, and another from the Karma project (previously Testacular - an Angular group project). These are all preceded and likely influenced by the original GIT project code contribution guide.

Essentially, these guides espouse a similar set of recommendations: recognizing some line length limits, keeping the mood/voice/tense consistently imperative, and having a standard set of types (and optionally a consistent set of scopes) that describe each commit.

Stephen's felt like the closest to what I was looking for, so that guide provided a solid basis for my first crack at a bluejava Git Commit Message Format.  In fact I could very well have just adopted Stephen's guidelines as-is and improved greatly upon what I had been doing.

Making a Clear Commitment

But there were a few changes I felt improved upon the format, so I created this derivative. Changes include:

  • types are ALL CAPITAL LETTERS to clearly distinguish them, and make them easier to filter/grep
  • The list of commit types is slightly different than others. ("chore" becomes "MAINT", "style" becomes "FORMAT", "refactor" is gone, and a new breaking change type called "BREAK")
  • The order of the list of types is important – when multiple types apply, the first type in the list should be used
  • Multiple types may also be specified (see guide for details).
  • Some recommendations such as not starting your subject line summary with a capital letter and omitting a period at the end have been dropped. I saw no value in controlling those details. (arguments to the contrary are welcomed!)
  • This format guide will live on Github and will be versioned and upgraded/updated over time. Forking of this guide is possible and welcomed.

View the complete guide here on Github. I will publish it initially as version 0.5.0 (and use SemVer conventions, as best as they apply to non-code). Once I've spent some time applying this to my own changes, I will move it to 1.0.

I encourage developers and development teams to standardize their commit messages if they haven't already. Point your team members to this guide - or fork this guide and customize it for your needs.

And of course I'd love to hear any ideas you all have to improve the format. 

Quick Reference

This is also present on the guide itself, and contained within the repository for the guide - but I am including it here too for convenience. I saved this to my desktop so I can easily display it whenever I make a commit:

Git Commit Message Format Quick Reference

 


If you or your organization could use a somewhat fanatical developer on your current or next project, lets talk. I am passionate about the user experience, easy to work with, and I get stuff done. Lets build something great!


Improving Your Change Logs - The bluejava Git Commit Message Format Tweet This!
Glenn is the founder of bluejava K.K., and has been providing consulting services and developing web/mobile applications for over 15 years. Glenn lives with his wife and two children in Fujisawa, Japan.
Comments
James Barlow
August 8, 2015
You can configure git to use a text file as a template for new commits. https://git-scm.com/book/tr/v2/Customizing-Git-Git-Configuration Checking back over my github commit log, I should be following your approach. It would make life easier.
August 8, 2015
Thanks for the tip James - that could be useful. One could even put the types/scopes in the template for a reminder that you could then delete and enter your message (or delete after you enter your message) Yah, I wish I had been following this in some of my bigger projects from day 1. Oh well, from here forward.. ;-)
James Barlow
August 8, 2015
You've got me thinking now. I never really played much with git hooks, but it looks pretty easy to incorporate format checks into the commit process. A script at repo/.git/prepare-commit-msg can add additional information and guidance to the default commit message. A script at repo/.git/commit-msg can enforce a policy and prevents a commit that doesn't (for example) start with a keyword, or any other regex magic. These are client-side hooks, but there are corresponding server-side methods as well. Atlassian seems to have the clearest docs on these hooks: https://www.atlassian.com/git/tutorials/git-hooks/local-hooks
August 8, 2015
Yes, thats a pretty good addition - at the very least just to catch the occasional typo. Perhaps I should write up an enforcement hook that matches the "spec" I wrote and throw it up on GitHub along with the guide. Then others could use it or easily copy/modify it to their needs. Thanks again James!
joanne
August 8, 2015
So now when you refactor your code, what do you use as the "TYPE"?
glenn
August 8, 2015
I thought about that a while and looked at my past changes and came to the conclusion that I rarely sat down and refactored code. Most often I refactored as part of a FIX or part of a FEATure. This may not be everyone's pattern - and if you tend to refactor as an atomic commit, it would probably be best for you to keep the REFACTOR type. And its not that I don't refactor; in fact I think it is because I constantly refactor whenever I touch code that I so rarely ONLY refactor. So for me, it wasn't worth the added type. I see each type as having a kind of cost. I think about how I will want to scan/grep the log, and if I had a REFACTOR type I would most often just include it with BREAK/FEAT/FIX since it is a code change. In the rare case that I do simply refactor code, I can just call it a FIX. Thanks for the question Joanne.
August 10, 2015
Got a question (via email) about how to view just specific types of commits, so I figured this may come in handy for someone else as well: Simple “grep” works just fine: git log --pretty=oneline | grep "FEAT" And if you want to check for multiple types, you need to use egrep or the “-E” option on grep to allow “extended regex”: git log --pretty=oneline | egrep "FEAT|FIX" Personally, I have an alias that I call “lg1” which equates to the following: lg1 = log --graph --abbrev-commit --decorate --date=relative --format=format:'%C(bold blue)%h%C(reset) - %C(bold green)(%ar)%C(reset) %C(white)%s%C(reset) %C(dim white)- %an%C(reset)%C(bold yellow)%d%C(reset)' —all This format looks better to me than the standard oneline format. So for me, I actually will be using: git lg1 | egrep "FEAT|FIX"
Dick Branson
August 9, 2018
Great article, Glenn! Why do you add a separate TYPE of BREAK and not just use FEAT. In what cases do you find it useful?
August 10, 2018
Thanks a lot Dick! BREAK would correspond with a MAJOR version increase and indicates an incompatibility with the previous version. Whereas a FEAT will *enhance* the software but maintain full backward compatibility. So users of your software library can safely upgrade to any MINOR version number within a given MAJOR version without fear of something breaking due to an update. The BREAK type is useful as it indicates the commit that is responsible for the breaking change.
(Comments currently disabled)