Writing Better Commit Messages

Writing Better Commit Messages

In this article, we will learn what commit messages are, and how to write commit messages in a consistent, readable way.

The guides here are not set in stone, and as such can be tweaked. What this guide aims at is getting us to gain some form of consistency and clarity with our commit messages

This article assumes we have a basic understanding of git. If you're unfamiliar with Git, you can check out git docs here.

What is a commit message?

As our codebase continues to grow, it is very important that we are able to understand all the changes we have made to our code. Inasmuch as we perfectly understand what is going on now, it is unavoidable that in some months' time, it might be difficult to get a grip of what’s going on. This is where commits come in.

A commit is a command that takes a snapshot of all the changes we have made in our project, and stores a unique reference to it. While creating a commit, we specify a message (this message is called a commit message) that tells us what was done and summarizes how this version of the project is different from the previous version. This way, we can always come back to our project - after a thousand years - and still know what exactly we did at any point in time in our project.

To add a commit, we use the command

git commit

Why the fuss about commit messages?

The ability to easily understand what is going on in a project at different points in time is a function of commit messages.

Good commit messages are important for maintaining long-term projects - whether it is a team project or a personal project. It helps us keep track of all the changes that were made for each commit.

A properly-written commit message is the most effective approach to convey context about a change to other developers working on the project, and also to yourself.

Writing better commit messages.

A standard commit message has 3 parts:

  • The header/subject

  • The body

  • The footer
<header>

[body (optional)]

[footer(s) (optional)]

The header/subject

The header can be divided into the type, the scope, and the description.

  • type. This tells us the reason why the change was made. This can take any of the following values:

    • fix. This tells us that a bug was fixed.

    • feat. This tells us that a new feature was added to the project.

    • perf. This is used to indicate a change in code that improves the performance of the project.
    • refactor. This indicates a change in code that does not add a new feature or fix a bug.
    • build. This includes changes that affect the build
    • ci. Indicates changes made to CI (Continuous integration) configuration files.
    • docs. This identifies changes made to the documentation.
    • style. Changes that update the style in a codebase (like formatting, tabs, white-space, etc). They do not affect the meaning of the code.
    • test. This is used when we add a new test or update existing ones.

    We can definitely add to the list, but whatever we add must be clearly defined and consistent across the project.

  • Scope. This is optional. It identifies the place of the commit change. This depends on the project. If the commit introduces breaking changes (A change in one element of a software system that causes failure in other areas.), it is necessary to include a ! after the type/scope.
  • Description. This is a short message that describes what the commit does. It is very important that the description of a commit message:

    • Is written in the imperative. E.g. Use implement instead of implemented or implements; use fix instead of fixed or fixes
    • Does not end it with a period (.)

    A good rule of thumb for a description is to substitute it in place of the dash in the statement below and see if it completes correctly.

If applied, this commit will ___

For example, take these two descriptions below:

Bad: Implemented a theme toggle

Good: Implement a theme toggle

When we substitute these messages in the template above, we have:

Bad: If applied, this commit will implemented a theme toggle
Good: If applied, this commit will implement a theme toggle

It is important that the header/subject is as precise as possible. It is best to limit it to 50 characters. This is not set in stone, but keeping it at this length ensures they are readable. In addition, the GitHub user interface works on this convention. If we go over the 50-character limit, it will alert us, and if the subject line exceeds 75 characters, it will truncate the rest of the line.

Github UI warns us when we exceed the 50 character mark

Github UI truncates the subject line after 75 characters

The Body

The body should be separated from the subject with a blank line. The body is used to explain what was changed and why the change was made.

It is important to wrap the body of your commit messages to 72 characters per line. This allows Git plenty of room to indent text while still keeping everything under 80 characters overall. Wrapping text at 80 characters stops the text from filling the whole width of your command line window, making commits easier to read.

We can separate the body into paragraphs separated by single blank lines. We can also add lists.

Example:

More detailed explanatory text, if necessary. Wrap it to about 72
characters or so. In some contexts, the first line is treated as the
subject of the commit and the rest of the text as the body. The
blank line separating the summary from the body is critical (unless
you omit the body entirely); various tools like `log`, `shortlog`
and `rebase` can get confused if you run the two together.

Explain the problem that this commit is solving. Focus on why you
are making this change as opposed to how (the code explains that).
Are there side effects or other unintuitive consequences of this
change? Here's the place to explain them.

Further paragraphs come after blank lines.

 - Bullet points are okay, too

 - Typically a hyphen or asterisk is used for the bullet, preceded
   by a single space, with blank lines in between, but conventions
   vary here

Not every commit messages necessitates the use of both a subject and a body. A single line indicating the subject can be sufficient in some cases, especially when the change is so little that no more context is required. Consider the following scenario:

docs: fix a typo in line 4 of the user guide

This is straightforward and does not require additional explanation. This type of one-line commit can easily be done on the command line by adding the -m option to git commit as so:

git commit -m “docs: fix a typo in line 4 of the user guide”.

But when a commit requires more context and explanation, we make use of the body. In this case, it is best not to include the -m option so we run the commit command directly

git commit

This opens an editor where we type our commit message. The default git editor for commit messages is Vim. You can configure git to use an editor of your choice. Check out this on Stack Overflow

The footer contains references to GitHub issues that the commit addresses. It can also contain any information about breaking changes.

Updating the model at the beginning of this article, we have

<type>[scope (optional)]: <description>

[body (optional)]

[footer(s) (optional)]

Example


feat: Summarize changes in around 50 characters or less

More detailed explanatory text, if necessary. Wrap it to about 72
characters or so. In some contexts, the first line is treated as the
subject of the commit and the rest of the text as the body. The
blank line separating the summary from the body is critical (unless
you omit the body entirely); various tools like `log`, `shortlog`
and `rebase` can get confused if you run the two together.

Explain the problem that this commit is solving. Focus on why you
are making this change as opposed to how (the code explains that).
Are there side effects or other unintuitive consequences of this
change? Here's the place to explain them.

Further paragraphs come after blank lines.

 - Bullet points are okay, too

 - Typically a hyphen or asterisk is used for the bullet, preceded
   by a single space, with blank lines in between, but conventions
   vary here

If you use an issue tracker, put references to them at the bottom,
like this:

Resolves: #123
See also: #456, #789

This example is gotten from here

The gospel of writing better commit messages is one we should actively follow and preach to other developers. I have not been a very good disciple in the past, but I promise to do better and you should promise to do better as well.

If you also promise to do better, say with me

I understand the importance of writing readable and consistent commit messages and I pledge to write better commit messages from now on. So help me git!

:)

I'm glad we followed through, and hopefully, we have broken the yoke of disorganized, unreadable, and inconsistent commit messages.

Signing out, Steph Crown ✌️