How to write a better Git Commit Message

Why having a good git commit history is important

How to write a better Git Commit Message

INTRODUCTION

At the beginning of a project, we have a lot of information to update our git commits but as time goes on, it begins to decline. As a newbie in the dev world, it's almost inevitable to mess up the commits at first especially if you are trying to figure it out with no help and coming up with good words OR writing isn't one of your strong suits ( just like me 😉).

When I made my first git commit, I didn't even understand properly the commit process. I would just commit all the files without staging any changes and then go on my GitHub and just be lost because I probably saw multiple files before commiting and could only see 1 after, due to the fact that I didn't stage the commits separately.

This was what my commit looked like at first 😶

github screenshot.png

And then, it became like this (still terrible) :

git screenshot.png

A recruiter saw my GitHub and sent me resources on creating a good message, and I figured out my git message which I thought had greatly improved still wasn't there yet.

Luckily for the both of us, we can improve our git commit message 👏🏾👏🏾👏🏾👏🏾.

Why a good git message is important

Imagine going through someone's git and seeing something like this;

$ git log --oneline -5 --author cbeams --before "Fri Mar 26 2009"

e5f4b49 Re-adding ConfigurationPostProcessorTests after its brief removal in r814. @Ignore-ing the testCglibClassesAreLoadedJustInTimeForEnhancement() method as it turns out this was one of the culprits in the recent build breakage. The classloader hacking causes subtle downstream effects, breaking unrelated tests. The test method is still useful, but should only be run on a manual basis to ensure CGLIB is not prematurely classloaded, and should not be run as part of the automated build.
2db0f12 fixed two build-breaking issues: + reverted ClassMetadataReadingVisitor to revision 794 + eliminated ConfigurationPostProcessorTests until further investigation determines why it causes downstream tests to fail (such as the seemingly unrelated ClassPathXmlApplicationContextTests)
147709f Tweaks to package-info.java files
22b25e0 Consolidated Util and MutableAnnotationUtils classes into existing AsmUtils
7f96f57 polishing

Terrible huh ? Can't even figure for the life of me, what's happening over here. Now lets take a look at this one:

$ git log --oneline -5 --author pwebb --before "Sat Aug 30 2014"

5ba3db6 Fix failing CompositePropertySourceTests
84564a0 Rework @PropertySource early parsing logic
e142fd1 Add tests for ImportSelector meta-data
887815f Update docbook dependency and generate epub
ac8326d Polish mockito usage

It is clean, clear and concise. You can easily figure things out independently which is what we aim for. We want other developers to be able understand at first sight what we have done or changed.

Why a bad commit message is a big deal

At some point, while working you want to go back and see some changes you have made. Maybe to confirm little details like when a bug was introduced or who created a particular piece of code. You should be able to figure this out easily just by looking through the revision history.

In an ideal situation, you want to be able to get some context and some thought process behind the changes made just by looking at the commit message.

In reality, if all you are looking at is a messed up git commit history containing things like fixed a bug commit1 😅 changed css property small change. These messages provide zero help and can prolong the time a developer could use completing some other important tasks because now you are left with no option than to go through the diff to figure things out that could have easily been figured out in a matter of minutes, if the commit message had been correctly done.

Peter Hutterer makes this point as well:

Re-establishing the context of a piece of code is wasteful. We can’t avoid it completely, so our efforts should go to reducing it [as much] as possible. Commit messages can do exactly that and as a result, a commit message shows whether a developer is a good collaborator.

If you haven’t given much thought to what makes a great Git commit message, it may be the case that you haven’t spent much time using git log and related tools. There is a vicious cycle here: because the commit history is unstructured and inconsistent, one doesn’t spend much time using or taking care of it. And because it doesn’t get used or taken care of, it remains unstructured and inconsistent.

But a well-cared for log is a beautiful and useful thing. git blame, revert, rebase, log, shortlog and other subcommands come to life. Reviewing others’ commits and pull requests becomes something worth doing, and suddenly can be done independently. Understanding why something happened months or years ago becomes not only possible but efficient.

A project’s long-term success rests (among other things) on its maintainability, and a maintainer has few tools more powerful than his project’s log. It’s worth taking the time to learn how to care for one properly. What may be a hassle at first soon becomes habit, and eventually a source of pride and productivity for all involved.

Improving the quality of your git commit.

Now that we understand the importance of a good commit message, lets figure out ways to improve our commits. As a new developer, we have to train ourselves to create good commit messages.

The first thing to focus on when creating a message for your commit is to keep your commit itself small. Once your commit is small, it makes it possible to give a descriptive message.

fixed some issue is not in anyway descriptive.

To come up with thoughtful commits, consider asking yourself these questions:

  • Why have I made these changes?

  • What effect have my changes made?

  • Why was the change needed?

  • What are the changes in reference to?

Take a little time and try to answer some of the questions to generate a more clear and concise git message.

Small commits also comes with great benefits, as it makes it easier to debug your code and a better code review process.

Projects

7 RULES OF A GREAT COMMIT

  • Separate subject from body with a blank line

  • Limit the subject line to 50 characters

  • Capitalize the subject line

  • Do not end the subject line with a period

  • Use the imperative mood in the subject line

  • Wrap the body at 72 characters

  • Use the body to explain what and why vs. how

a) Separate subject from body with a blank line: Not every commit requires both a subject and a body. Sometimes a single line is fine, especially when the change is so simple that no further context is necessary. For example:

Change header image 
fix footer class name

One can easily view the changes made itself using git show or git diff or git log -p. To commit something like this at the command line, it’s easy to use the -m option to git commit:

$ git commit -m "Fix typo in introduction to user guide"

When a commit merits a bit of explanation and context, you need to write a body. For example:

Derezz the master control program

MCP turned out to be evil and had become intent on world domination.
This commit throws Tron's disc into MCP (causing its deresolution)
and turns it back into a chess game.

b) Limit the subject line to 50 characters: We talked about this earlier.

If you’re having a hard time summarizing, you might be committing too many changes at once. Strive for short commits

c) Capitalize the subject line: Begin all subject lines with a capital letter. Example:

Add hamburger menu button

instead of

add hamburger menu button

d) Do not end the subject line with a period: Trailing punctuation is unnecessary in subject lines. Besides, space is precious when you’re trying to keep them to 50 characters or less. For example

Fix header

instead of

Fix header.

e) Use the imperative mood in the subject line: The change summary is often written in the Imperative mood which means "spoken or written as if giving command or instruction". for example:

Remove deprecated methods
refactor subsystem X
merge pull request #123

instead of

fixed bug with Y
changing behavior of X

The imperative mood might sound rude and writing this way can be a little awkward at first (for me at least). We’re more used to speaking in the indicative mood, which is all about reporting facts. That’s why commit messages often end up reading like this:

Fixed hover problem under shell class.

when you write your commit messages in the imperative, you’re following Git’s own built-in conventions. For example, the default message created when using git merge reads:

Merge branch 'myfeature'

And when using git revert:

Revert "Add the thing with the stuff"

This reverts commit cc87791524aedd593cff5a74532befe7ab69ce9d.

Or when clicking the “Merge” button on a GitHub pull request:

Merge pull request #123 from someuser/somebranch

To remove any confusion, here’s a simple rule to get it right every time.

A properly formed Git commit subject line should always be able to complete the following sentence:

If applied, this commit will your subject line here for example,

If applied, this commit will merge pull request #123 from user/branch
If applied, this commit will refactor subsystem X for readability
If applied, this commit will Change header image on main page

Notice how this doesn’t work for the other non-imperative forms:

If applied, this commit will fixed bug with Y
If applied, this commit will changing behavior of X
If applied, this commit will more fixes for broken stuff

Remember: Use of the imperative is important only in the subject line. You can relax this restriction when you’re writing the body.

f) Wrap the body at 72 characters: Git does not automatically wrap text. When writing the body of a commit message, keep the right margin in mind and wrap text manually.

The recommended length is 72 characters, which gives Git plenty of room to indent text while still keeping the overall length under 80 characters.

g) Use the body to explain why vs how:

This commit from free code camp is a great example of explaining what changed and why:

fix: fix foo to enable bar 

This fixes the broken behavior of the component xyz. 

BREAKING CHANGE 
Before this fix, foo wasn't enabled at all. Behavior changes from <old> to <new> 

closes F200-12345

Just see this full diff and think of your future self or another developer having to fix something and seeing this in full context in display. That's a different kind of joy right there. In most cases, you can leave out details about how a change has been made. Code is generally self-explanatory in this regard (and if the code is so complex that it needs to be explained in prose, that’s what source comments are for). Just focus on making clear the reasons why you made the change in the first place—the way things worked before the change (and what was wrong with that), the way they work now, and why you decided to solve it the way you did.

In a team

I haven't gotten my first job as a developer yet, but I have read good things about git messages on projects worked on in a team. Following your team's work convention is the most important. As a new developer, asking lots and lots of questions until you get clarity on the how's, when's and what's is a way to build a great foundation at your new workplace. This way you don't mess up the process.

You should structure your commit messages in a certain format. To create useful revision history. This format again, is agreed on by your team on a convention to use. An example will be ;

Style. Markup syntax, wrap margins, grammar, capitalization, punctuation. Spell these things out, remove the guesswork, and make it all as simple as possible. The end result will be a remarkably consistent log that’s not only a pleasure to read but that actually does get read on a regular basis.

Content. What kind of information should the body of the commit message (if any) contain? What should it not contain?

Metadata. How should issue tracking IDs, pull request numbers, etc. be referenced?

Conclusion

Writing a good commit message is a great skill to develop and it helps you communicate and collaborate with your team. Commits serve as an archive of changes. They can become an ancient manuscript to help us decipher the past, and make reasoned decisions in the future.

I hope you learned something new today and will implement what you learnt just like i am about to😊