How to write a commit message that will make your mom proud

Here are some guidelines on how to best structure and write a commit message, especially if you are using GitHub to host your git repository.

WARNING: This is a highly opinionated article and could cause some developers to lose their minds. I do not claim responsibility for all lost minds caused as a result of reading this article.

Commit anatomy

Before going over the guidelines, it's best to review the anatomy of a commit message.

A commit message is comprised of a subject, body, and footer, with both the body and footer being optional. The subject is a single line that best sums up the changes made in the commit. The body text is used to provide more details regarding the changes made in the commit. The footer text is found immediately below the body and is a place to reference issues related to the commit changes. The body is separated by the subject by an empty line and similarly, the footer is separated from the body by an empty line.

Example commit message

text
1Add end-to-end test to shopping cart page
2
3This adds several tests to the shopping cart page to catch potential regressions
4introduced to the payment flow by the addition of new features.
5
6The following functionality is tested:
7- Adding multiple items to the cart
8- Removing items from the cart
9- Adding discount code to the cart
10- Sending the user to payment details page when pressing the payment button
11
12Issue #123

Subject line less than or equal to 72 characters in length

To prevent a commit message's subject to be cut off in GitHub, make sure to limit the character length to 72 characters. This character limit is irrespective of the character width (i.e. even if an "I" character takes up less horizontal space than a "W" character in the GitHub UI, you will not be able to display more than 72 "I" characters).

72 "W" characters in the GitHub UI.
No cutoff text shown when using 72 "W"s for the commit message subject.

72 "I" characters in the GitHub UI.
Just like with wide "W" characters, 72 "I" characters will appear just fine.

73 "W" characters in the GitHub UI.
The commit subject gets cutoff when there are 73 "W"s. What ends up showing up are 69 "W"s in the main upper area with 3 dots that will reveal the remaining 4 "W" when clicked.

72 "I" characters in the GitHub UI.
Again, similar to the "W" characters, 73 "I" characters in the commit subject will be displayed as cutoff, with the cutoff text reveal only when clicking the 3 dots.

Body line length limited to 80 characters

The line length for the body text of a commit message should be constrained to 80 characters. Regardless of if you manually wrap the body line length to 80 characters or not, the body text will appear as wrapped as 80 characters in the GitHub UI. However, limiting the line length to 80 characters makes commit messages more readable when trying to read them in the command line (such as when executing the command git log).

Non-constrained commit message body text in the GitHub UI.
Here's how a commit message looks like in GitHub when not manually limiting the line length. Notice the text is automatically constrained to an 80 character line-length limit.

Commit body spanning the full width of the command line.
However, if the line length is not manually constrained to 80 characters, the commit body will span the full width of the command line making the commit message more difficult to read.

Commit body spanning a maximum of 80 characters in line length in the command line.
Wraping text at 80 characters prevents text from spanning the full width of your command line window and allows for better readability of commits.

The reason why having text span a large line length makes things less readable is because when reading multiple lines of text, your eyes need to be able to jump from the end of one line of text to the beginning of the next line of text. Having a longer line length makes this visual jump more difficult. This is easily illustrated by trying to read text that has a long line-length and a very small line-height (decreased line-height exacerbates this issue).

Here's a look how the message body looks like in GitHub when manually limitting line length to 80 characters.
Notice how difficult this paragraph with a long line length is to read. This is because your eyes require more effort to identify the start of the next line.

The only issue I see with wrapping body messages at 80 characters is that when you open a new pull request on GitHub and the pull request only has a single commit (which is a majority of my pull requests), GitHub will populate the pull request description with the text from the commit message body. With the text wrapped at 80 characters, there will be some whitespace in the pull request description. If you did not limit the commit body line length to 80 characters, then the default pull request description will fill the full space of the pull request description. Yes, you can simply remove this whitespace manually in the pull request description, but it's slightly annoying.

Here's a look at the whitespace that is left in the pull request description when wrapping commit message body text at 80 characters.
Here's a look at the whitespace that is left in the pull request description when wrapping commit message body text at 80 characters.

Another look at the whitespace in the pull request description when not in "edit mode".
Another look at the whitespace in the pull request description when not in "edit mode".

Use sentence case for commit subject line with no period

Use sentence case (without an ending period) for the commit subject line. This makes the subject read like the header for an article section. The commit body text should be punctuated and cased as you would expect from any normal paragraph of text (i.e. sentence case with periods).

Example

text
1Fix the lag while typing in the search bar
2
3Now the logic for filtering the search results is debounced which gets rid of
4the noticeable lag that appeared while typing in the search bar.

Use present tense imperative for the subject line and present tense for body text

The present imperative should be used for the subject line of commit messages. This is what has been standardized by git itself. For example, when merging one branch into another, git will search a commit message in the form of Merge branch 'branch-name'.

For a good discussion diving into the pros and cons of present vs past tense, see this stack overflow post.

The footer is the perfect place to reference issues that are affected by changes made in the commit. For example, if using JIRA to manage your project tasks, then refer to any JIRA issues in the footer.

text
1Fix the lag while typing in the search bar
2
3Now the logic for filtering the search results is debounced which gets rid of
4the noticeable lag that appeared while typing in the search bar.
5
6Issue ABC-1337

Decide on a format on how you want to list issues in the footer and stick with it. Also, GitHub has a feature that allows you to automatically create links from text that matches a specific pattern in a pull request description. Therefore, if creating a pull request that has a single commit, the pull request description will include the commit message footer and if it matches the format you've configured in the GitHub settings, it will generate a link for you automatically (e.g. a link pointing the JIRA issue) 🎉.

Using VSCode to write commit messages

Most times I write my commit messages from the command line, but if I expect to write a long commit message, I'll usually do so in VSCode.

You can set VSCode as your default git editor by first installing the VSCode command-line interface and then execute the following command in your shell:

bash
1git config --global core.editor "code --wait"

With VSCode set as your default git editor, whenever you execute git commit, VSCode will open up for you to type in your commit message. The commit message is saved once you've closed the VSCode tab (can be done with ⌘ + w). What is especially nice about this is that you can configure VSCode to set vertical rulers that can act as guides for the line length limits you wish to follow:

Vertical line rulers indicating character line limits for both the commit subject (72 characters) and body (80 characters).

To set these rulers, just add the following to the VSCode global settings.json file:

1"[git-commit]": {
2 "editor.rulers": [72, 80]
3}

It's worth mentioning that there are some great tools out there related to commit guidelines and enforcing commit message rules.

Conventional Commits

Conventional Commits is a commit convention that is useful for describing how commit changes are related to the semantic version of an app as well as enable for some automated tooling that can leverage this specific commit convention. These types of commits take the following form:

1feat(home): add signup link to home page
1fix(signup): allow signup button to be clicked

This is a very popular commit standard that is followed, but unless you want to do some things like automatically generate changelogs or automatically bump semantic version numbers, this convention is probably overkill.

Commitlint

Commitlint is a tool to help enforce commit rules, such as line lengths, required empty lines between subject/body/footer, and more.

Final note

Keep in mind that a lot of the above is based on personal preference and you may want to use another convention when writing your commit messages. The most important thing that should be maintained, no matter what your preference may be, is consistency.



Robert Cooper's big ol' head

Hey, I'm Robert Cooper and I write articles related to web development. If you find these articles interesting, follow me on Twitter to get more bite-sized content related to web development.