DEV Community

Cover image for Write Git Commit Messages That Your Colleagues Will Love
Simon Egersand 🎈
Simon Egersand 🎈

Posted on

Write Git Commit Messages That Your Colleagues Will Love

Git commit messages are how we communicate to our future selves. They help you understand why a certain line of code was added to the code base. That's why knowing how to write a good Git commit message is important.

We've all been there; "Git is confusing", "Why can't I just push to the main branch?", "No one will ever read this message". These thoughts are normal and most people that have learned Git can probably relate. You might not appreciate good commit messages until you work with a code base that's been around for years. Or when you return to an old project of yours.

In this article, I'll show you how to write Git commit messages that you and your colleagues will love.

Why Git Commit Messages Are Important

Have you opened up an old project and checked the commit messages with git log? If not, I recommend you do that now. If they're not filled with "Fix styling" or "Add endpoint" then great job! If you're like the rest of us, read on πŸ˜„

Or perhaps you joined a company with a code base that's been around for a few years. And you're trying to understand why some piece of code was added. Will you break anything if you change it? In this case, a good commit message is invaluable.

Simply put, by writing good Git commit messages you are future-proofing yourself and your colleagues. And as developers, we are reading a lot more code than writing it.

Reading vs. Writing Code

Uncle Bob (Robert C. Martin - author of popular programming books such as Clean Code) says

β€œIndeed, the ratio of time spent reading versus writing is well over 10 to 1. We are constantly reading old code as part of the effort to write new code. ...[Therefore,] making it easy to read makes it easier to write.” (ref.)

At times, to understand the code you will also need to read the commit message. I hope that you now see that the effort of writing a good commit message is worth it!

How To Write Good Git Commit Messages

Now that you're convinced that commit messages are important, let's look at how you can write them in a way that your colleagues will love!

A commit message consists of two parts: the subject line and the body. Here's an example from the bitcoin repo.

commit eb0b56b19017ab5c16c745e6da39c53126924ed6
Author: Pieter Wuille <pieter.wuille@gmail.com>
Date:   Fri Aug 1 22:57:55 2014 +0200

   Simplify serialize.h's exception handling

   Remove the 'state' and 'exceptmask' from serialize.h's stream
   implementations, as well as related methods.
   ...
Enter fullscreen mode Exit fullscreen mode

The first line is the subject and what follows after the new-line is the body.

Focus On The Why

This is the most important rule. And it's also the most common mistake. Commit messages should explain why the code was added, not what was added. To see the what I can just read the code. But to understand the why I can only guess.

Even if I'm the author of the code, I will eventually forget the why.

Use Imperative Mood In The Subject Line

Imperative mood means "used to demand or require that an action be performed". This is the mood Git uses by default, and so should you.

For example, the git revert command will create a so-called "revert commit" for you. This commit will have a subject line with an imperative mood - "Revert 'Add field to schema'".

You can think about it that you are telling the system/app/etc. how to behave. This might be awkward at first but you'll get used to it.

Note: You can write in whatever mood you prefer for commit bodies.

Restrict Subject Line Length to 50 Characters

Have you ever seen a commit message on GitHub that ends with ...? That's because GitHub truncates the subject line if it goes above 72 characters. The rest of the subject line moves to the commit body.

50 characters is the recommendation by GitHub. The limit exists to make the commit more readable. And you're forced to explain your code changes in a concise and comprehensible way.

If you're having problems explaining your code changes with 50 characters you might be committing too many changes at once. If this is the case, you should split the commit into multiple commits.

Conclusion

These are the three most important rules to follow when writing Git commit messages. If you follow these rules your colleagues will quickly understand what the commit is about.

To summarise:

  • Focus On The Why
  • Use Imperative Mood In Subject Line
  • Restrict Subject Line Length to 50 Characters

To learn more git commit best practices, check out this excellent blog post.


Connect with me on Twitter, LinkedIn, or GitHub

Discussion (29)

Collapse
snikhill profile image
Nikkhiel Seath

Yep, definitely nice tips.

I also recommend the Conventional Commits Pattern.
And keeping the commits atomic (but, maybe I am baised as I gave talk on that topic 😁)

Collapse
dikamilo profile image
dikamilo

I love Conventional Commits. They also works great with semantic-release.

Collapse
simeg profile image
Simon Egersand 🎈 Author

Love that link, thanks for sharing it! Yes, agree. Atomic commits are the best :)

Collapse
jcubic profile image
Jakub T. Jankiewicz

It would be nice to see good example of a commit message, since Bitcoin commit that you've added is not good example. It shows what was done, not why which is later explaned that it's not a good thing.

Collapse
simeg profile image
Simon Egersand 🎈 Author

Good point! I might edit this post later and add it :) Thanks for the advice.

Collapse
vaso profile image
Vaclav Elias

Yes please, if you advise this, included examples would be so helpful.

Collapse
tandrieu profile image
Thibaut Andrieu

Some commit convention also requires to add the step to reproduce, previous result and new result in case of commit fixing a bug.

On my side, I would prefer keeping behavioral information in the issue tracker, and keep in the commit only the technical explanations, like why this modifications of code fix the issue #426 for instance.

What is your opinion about this ?

Collapse
simeg profile image
Simon Egersand 🎈 Author

Hi! Good question!

Personally I think such information could go in the Pull Request and not in the commit. Commits should be atomic and describe, like you said, the technical changes.

Issue trackers are good for tracking the issues. By referencing a ticket in the issue tracker you are creating a dependency. Later, you might decide to change issue tracker system, and all your ticket references in Git are useless. So you should not put all information in the issue tracker.

It's a fine balance and I agree with what you said :)

Collapse
bigpresh profile image
David Precious

Your point on changing issue tracker system and losing all the info you'd referred to from your commits is a good argument in favour of making sure that the salient info is in commit messages not pull requests, though.

Imagine in a few years you decide GitHub is no longer right for you. There may be a good migration path to some other provider you choose, or there may not. As you already have your Git repo checked out, you can just push it to some other Git host, or self-host, and you've not lost any of those years of commit messages, even if the information on GitHub pull requests wasn't able to come along.

Thread Thread
simeg profile image
Simon Egersand 🎈 Author

This is a good point. Again, it's the question of balance. Should you put all the context everywhere? Probably not. For various reasons. Should you put enough context in a commit for it to make sense? Yeah, probably.

Changing systems is always a risk that we have to live with. And hope that if/when we migrate we can migrate all data :D

Thread Thread
tandrieu profile image
Thibaut Andrieu

Regarding changing issue tracker, I went through (bugzilla ?)->Elementool->Redmine->Jira->Another Jira.
I think Bugzilla database has been lost as I never saw it but I've heard talking about Bugzilla in coffee long long time ago.
If I remember well, Elementool database has been ported to Redmine with some "one shot script". Elementool Ticket number was written in a Redmine custom field, so we can make the link between commit message and ticket. In commit message, Elementool issues was with the form "#1234". So we use the convention "RM1234" for new Redmine ticket. It was easy to know where the ticket came from.

For first Jira migration, Redmine was an on premise server. So for our team we kept it alive in read only access, create new ticket on Jira and that's it. It was a mess for a few weeks, time for WIP ticket to be closed, but not that an issue.
Some other teams have duplicated their Redmine database to the Jira instance, which was the worst idea ever as their brand-new Jira instance has been flooded with thousands of useless legacy tickets and years of custom fields entropy...
Migration from Jira1 to Jira2 was quite smooth, as it was Jira propose an import system.

Looking back, having a database migration once every few year is not really an issue compare to every day constrains on commit message. Steps to reproduces HAVE to be in ticket anyway, because it is the interface between customer, hotline and developers, so better keep it in a single place than duplicating the information both in ticket and in commit message.

Collapse
paulknulst profile image
Paul Knulst

Nice article about commit messages. The basic rules you describe are important. I did the same until I found out about Conventional Commits Pattern. I would suggest that you try it at least once.

It has several benefits in terms of readability, maintainability, or if you want to revert to a specific point without investigating much.

Furthermore, it works with SemVer (semantic version). This means, you can generate changelog files automatically!

Some months ago, I wrote an article on Medium about that pattern: betterprogramming.pub/write-better...

Check it out! Until today, the feedback I got was really positive. I have also adopt the pattern at work and everyone loves it.

Collapse
aktentasche profile image
Jonas Manthey

Examples would have been nice, I have no idea what you mean by "imperative mood".

Collapse
simeg profile image
Simon Egersand 🎈 Author

I see now that examples would be useful.

For ref., imperative mood is when you tell someone to do something.

Imperative mood
Add field to schema

Present Subjunctive (I think .. )
Added field to schema

Present Subjunctive mood is the most common verb mood I see when not using Imperative mood. Git uses imperative mood so it makes sense to follow the same principle.

Collapse
desireebyrd profile image
desireebyrd • Edited on

So I probably SHOULDN'T add 7 commits in a row with variations of "Work, damn you!" then, right? ;-)

Collapse
drazisil profile image
Drazi Crendraven

πŸ€·β€β™€οΈπŸ€£πŸ˜‡ "Works for me"

Collapse
pictor13 profile image
Igor Pellegrini

"Works on my machine" !!

Collapse
simeg profile image
Simon Egersand 🎈 Author

Whatever floats your boat :D

Collapse
krishnaagarwal profile image
Krishna Agarwal

Great Tips πŸ˜„
Thanks πŸ‘

Collapse
simeg profile image
Simon Egersand 🎈 Author

Thanks, Krishna! :)

Collapse
bobbyiliev profile image
Bobby Iliev

Very cool!

Collapse
jmccabe profile image
John McCabe

Bit of a sudden ending to the story; I thought you might continue to talk about the (much neglected) body, and why you shouldn't accept the default message on merge commits when your source and destination branch have the same name (when there's a reasonable chance a rebase would be more appropriate).

Collapse
pictor13 profile image
Igor Pellegrini

I also was hoping in more juice about the body. It's a whole topic itself.
Commit titles are imho easy to write; and they don't really solve the "lack of context" problem. That's what commit body is for: the details that one will spend hours/days to guess/investigate by themselves.

Stuff like:

  • examples of a newly added command with description of options/parameters (as most of the times we don't add enough markdown documentation)
  • a reference to multiple tickets or, better, special keywords to interact with rather than just referring them (e.g. close a ticket with a commit). Or even references to multiple ticketing systems (I use Redmine for corporate collaboration and Gitlab issues more for self-management)
  • TODOs or missing features (as described above, an Issue Tracking System might not be available one day)
  • insights on what dirty detail of the code forced to perform the changes brought by the commit
  • if it makes sense to use Markdown or formatted code in the commit body (sometimes it does)
  • what kind of URLs or references makes sense to add

There are just some of the aspects that I find myself dealing with into commits' body.

Collapse
annetawamono profile image
Anneta Wamono

When I commit with a message on the command line, I think I'm only able to add a subject line. Is there a way to add a commit body through command line?

Collapse
algonzalez profile image
Al Gonzalez • Edited on

You can use the -e or --edit option which will open your configured editor.
You can also use the -m option multiple times and the text will be concatenated as separate paragraphs.
Another method is to pipe the comment to a file and use either the -F <file> or --file=<file> option.

Running git help commit should show you all the possible options.

HTH

Collapse
simeg profile image
Simon Egersand 🎈 Author

I guess you do something like

git commit -m "Add field to schema"
Enter fullscreen mode Exit fullscreen mode

Instead you can do

git commit
Enter fullscreen mode Exit fullscreen mode

And git will open up your favorite editor (it defaults to $EDITOR I think) and you can put in a subject and body there. You separate them by a newline.

Collapse
martinhaeusler profile image
Martin HΓ€usler

In a monorepo context, it turned out to be a great idea to prefix the headline with the projects affected by the commit. For example:

[Admin UI] Added option to mass edit users.

Collapse
simeg profile image
Simon Egersand 🎈 Author

I considered including this in the post. I agree, especially for monorepos it makes sense. Just gotta find that good balance so the prefixes don't take up too many characters!

Collapse
pictor13 profile image
Igor Pellegrini • Edited on

Probably codifying the project name or the topic to 3-5 letters should work.
Same as many prefix with bug, fix, feat, ui, etc.

There are also several repos providing a model for emojii commits (a decent one, for example)
I really liked the ideas a lot (as long as a legend is provided somewhere in the repo) and started to use them happily (you can even filter commits by emoji/category)....
... until our sysadmin complained when the (draconian) issue-tracking-system crashed because of poor unicode support and told me to stop.... πŸ˜’