Skip to content

Instantly share code, notes, and snippets.

@lisawolderiksen
Last active March 18, 2024 16:11
Star You must be signed in to star a gist
Save lisawolderiksen/a7b99d94c92c6671181611be1641c733 to your computer and use it in GitHub Desktop.
Use a Git commit message template to write better commit messages

Using Git Commit Message Templates to Write Better Commit Messages

The always enthusiastic and knowledgeable mr. @jasaltvik shared with our team an article on writing (good) Git commit messages: How to Write a Git Commit Message. This excellent article explains why good Git commit messages are important, and explains what constitutes a good commit message. I wholeheartedly agree with what @cbeams writes in his article. (Have you read it yet? If not, go read it now. I'll wait.) It's sensible stuff. So I decided to start following the seven rules he proposes.

...There's only one problem: My mind is already stuffed with things I should do and things to remember. The chance of me remembering every rule every time I commit something, are next to 0. So I made myself a Git commit message template. That way, I don't have to remember the rules, they are presented to me whenever I write a commit message. So now, when I do git commit, this is what I see in my editor:

# Title: Summary, imperative, start upper case, don't end with a period
# No more than 50 chars. #### 50 chars is here:  #

# Remember blank line between title and body.

# Body: Explain *what* and *why* (not *how*). Include task ID (Jira issue).
# Wrap at 72 chars. ################################## which is here:  #

# At the end: Include Co-authored-by for all contributors. 
# Include at least one empty line before it. Format: 
# Co-authored-by: name <user@users.noreply.github.com>
#
# How to Write a Git Commit Message:
# https://chris.beams.io/posts/git-commit/
#
# 1. Separate subject from body with a blank line
# 2. Limit the subject line to 50 characters
# 3. Capitalize the subject line
# 4. Do not end the subject line with a period
# 5. Use the imperative mood in the subject line
# 6. Wrap the body at 72 characters
# 7. Use the body to explain what and why vs. how

# Please enter the commit message for your changes. Lines starting
# with '#' will be ignored, and an empty message aborts the commit.
#
# On branch master
# Your branch is up to date with 'origin/main'.
#
# Changes to be committed:
#       new file:   installation.md
#

What I see consists of two parts; first my own template, then Git's standard message asking me to "Please enter the commit message". No need to remember everything - or really much at all, except to not use git commit -m "Commit message", as this means I won't see the template I made.

NOTE: This kind of "template", strictly speaking consisting only of "commented out" stuff, depends on the commit.cleanup config being strip so the comments will be stripped out (ignored) in the commit message. strip is the default setting, so if you haven't changed it you should be good. (Thanks, @devdrops, for making me aware of this.)

Template File

Here is my template*, which i put in a file called .gitmessage in my home directory:

# Title: Summary, imperative, start upper case, don't end with a period
# No more than 50 chars. #### 50 chars is here:  #

# Remember blank line between title and body.

# Body: Explain *what* and *why* (not *how*). Include task ID (Jira issue).
# Wrap at 72 chars. ################################## which is here:  #


# At the end: Include Co-authored-by for all contributors. 
# Include at least one empty line before it. Format: 
# Co-authored-by: name <user@users.noreply.github.com>
#
# How to Write a Git Commit Message:
# https://chris.beams.io/posts/git-commit/
#
# 1. Separate subject from body with a blank line
# 2. Limit the subject line to 50 characters
# 3. Capitalize the subject line
# 4. Do not end the subject line with a period
# 5. Use the imperative mood in the subject line
# 6. Wrap the body at 72 characters
# 7. Use the body to explain what and why vs. how

Git Configuration

To tell Git to use the template file (globally, not just in the current repo), I used the following command:

git config --global commit.template ~/.gitmessage

And that's all there was to it. (Except I have my dotfiles in a repo, so I had to do some symlinking and update one of my config-scripts to be able to recreate this setup from scratch if I need to.)

Links and Documentation

The Git documentation contains a chapter on Customizing Git - Git Configuration which in turn contains a section on the commit.template configuration value.

Better Commit Messages with a .gitmessage Template has a different kind of template, which is an actual template: It contains text which will become a part of the commit message.

I also made a Gist on Adding co-authors to Git commits to share the credit for collaborative efforts.

Addendum

An easy way to get this config using a single command:

printf "# Title: Summary, imperative, start upper case, don't end with a period\n# No more than 50 chars. #### 50 chars is here: #\n\n# Remember blank line between title and body.\n\n# Body: Explain *what* and *why* (not *how*). Include task ID (Jira issue).\n# Wrap at 72 chars. ################################## which is here: #\n\n\n# At the end: Include Co-authored-by for all contributors. \n# Include at least one empty line before it. Format: \n# Co-authored-by: name <user@users.noreply.github.com>\n#\n# How to Write a Git Commit Message:\n# https://chris.beams.io/posts/git-commit/\n#\n# 1. Separate subject from body with a blank line\n# 2. Limit the subject line to 50 characters\n# 3. Capitalize the subject line\n# 4. Do not end the subject line with a period\n# 5. Use the imperative mood in the subject line\n# 6. Wrap the body at 72 characters\n# 7. Use the body to explain what and why vs. how\n" > ~/.gitmessage && git config --global commit.template ~/.gitmessage

Thanks a lot to @manav148, @rany2 and @drjasonharrison for the suggestions in the comments! The command I included above includes some updates I made to the template that were not there at the time of the comments; the line length indicators and the missing space in the first item of the numbered list.

Footnotes

*) It may be argued that this is, strictly speaking, not a template, as no part of it is actually used/included in the commit message. :)

@DervishD
Copy link

Hi Lisa!

First of all, thanks for the template, quite useful if you ask me, specially when one is writing commit messages in a hurry, and SPECIALLY when one is collaborating with other developers. Brillian πŸ‘

One question, though. The markers for the 50 and 72 limits are off-by-one (they point at 49 and 71 chars, respectively). Is this on purpose, to accommodate newlines? Because in my experience this is not needed, you can use the full 50/72 chars and have newlines without problem, even though I may be utterly wrong, of course. I'm just curious...

Again, thanks!

@lisawolderiksen
Copy link
Author

First of all, thanks for the template, quite useful if you ask me, specially when one is writing commit messages in a hurry, and SPECIALLY when one is collaborating with other developers. Brillian πŸ‘

You're very welcome! I'm glad you find it useful. πŸ˜„

One question, though. The markers for the 50 and 72 limits are off-by-one (they point at 49 and 71 chars, respectively). Is this on purpose, to accommodate newlines? Because in my experience this is not needed, you can use the full 50/72 chars and have newlines without problem, even though I may be utterly wrong, of course. I'm just curious...

No worries. I use the # to signal the last character within the 50/72 char limit. So when I type my commit message, I make sure that the last character I write is before or at the # mark. Just my quirky way of thinking, I guess. πŸ˜ƒ

@DervishD
Copy link

Thanks a lot for the explanation. And again, for the template. Now my only concern is that Visual Studio Code supports commit templates with commented lines without stripping the comments, rendering them useless. For now, I'll use your template with my ol' faithful Vim ;)

Happy coding!

@goswamia
Copy link

Hi,
Thanks a lot for sharing this file. But I am facing one issue, when I am trying to commit this I always get abort error message. any input

@Paul-weqe
Copy link

@goswamia I can see I am a couple of months on this. Don't know if you ever got your answer.

If you didn't, could you look if you have any post-commit hooks running ?

@drjasonharrison
Copy link

I think you want a space inserted between the "1." and "Separate subject from body with a blank line"

@manav148
Copy link

manav148 commented Jan 12, 2022

For the procrastinators out there;

printf "# Title: Summary, imperative, start upper case, don't end with a period\n# No more than 50 chars. #### 50 chars is here: #\n\n# Remember blank line between title and body.\n\n# Body: Explain *what* and *why* (not *how*). Include task ID (Jira issue).\n# Wrap at 72 chars. ################################## which is here: #\n\n\n# At the end: Include Co-authored-by for all contributors. \n# Include at least one empty line before it. Format: \n# Co-authored-by: name <user@users.noreply.github.com>\n#\n# How to Write a Git Commit Message:\n# https://chris.beams.io/posts/git-commit/\n#\n# 1.Separate subject from body with a blank line\n# 2. Limit the subject line to 50 characters\n# 3. Capitalize the subject line\n# 4. Do not end the subject line with a period\n# 5. Use the imperative mood in the subject line\n# 6. Wrap the body at 72 characters\n# 7. Use the body to explain what and why vs. how\n" > ~/.gitmessage && git config --global commit.template ~/.gitmessage

Edited as per @rany2 and @drjasonharrison comments

@drjasonharrison
Copy link

@manav148 echo doesn't expand \n, you should use printf. Did you test this?

@manav148
Copy link

Yes I used the command to setup on the mac.

@rany2
Copy link

rany2 commented Jan 12, 2022

echo does different things on different OSes and shells. Some don't even have -e to expand backslashes. For anything advanced, use printf. I guess what happened is that @drjasonharrison was on bash which doesn't expand backslashes by default (needs -e) and @manav148 uses zsh which does...

For the lazies, this one should work everywhere:

printf "# Title: Summary, imperative, start upper case, don't end with a period\n# No more than 50 chars. #### 50 chars is here: #\n\n# Remember blank line between title and body.\n\n# Body: Explain *what* and *why* (not *how*). Include task ID (Jira issue).\n# Wrap at 72 chars. ################################## which is here: #\n\n\n# At the end: Include Co-authored-by for all contributors. \n# Include at least one empty line before it. Format: \n# Co-authored-by: name <user@users.noreply.github.com>\n#\n# How to Write a Git Commit Message:\n# https://chris.beams.io/posts/git-commit/\n#\n# 1.Separate subject from body with a blank line\n# 2. Limit the subject line to 50 characters\n# 3. Capitalize the subject line\n# 4. Do not end the subject line with a period\n# 5. Use the imperative mood in the subject line\n# 6. Wrap the body at 72 characters\n# 7. Use the body to explain what and why vs. how\n" > ~/.gitmessage && git config --global commit.template ~/.gitmessage

@ALiwoto
Copy link

ALiwoto commented Jan 12, 2022

Thanks for the template.

@ryankearney
Copy link

$ echo -n "# No more than 50 chars. #### 50 chars is here: #" | wc -m                                                                                                                                                                                                                                                                                        
      49
$ echo -n "# Wrap at 72 chars. ################################## which is here: #" | wc -m
      71

Close, but off by 1.

@drjasonharrison
Copy link

@ryankearney as noted before the limits are the last valid column, not the first invalid column.

@rjray
Copy link

rjray commented Jan 12, 2022

Great template, I plan to use it (or a close simile) going forward!

One edit, though... this line:

# 1.Separate subject from body with a blank line

should maybe have a space between the number and the "S"?

@joelparkerhenderson
Copy link

Here's our similar git commit template with extras that can help with tag categories, keyword searches, and issue tracker links:

https://github.com/joelparkerhenderson/git-commit-template

@ryankearney
Copy link

ryankearney commented Jan 13, 2022

@drjasonharrison your explanation did not make sense, since β€œat the # mark” would be 49 and 71 characters respectively, not 50 and 72.

Let’s say we wanted the limit to be 10. If we marked it with 10-1 it would look like this.

###TEST##
1234567890

Note the 10th character is beyond the end of the 9th character (#)

A proper guard would include all 10 characters.

###TEST###
1234567890

@DervishD
Copy link

@ryankearney look a the second message on this thread, just after mine. @lisawolderiksen explains why she chose to do that, it's not a matter of correctness, but a matter of preference.

@marcelarie
Copy link

marcelarie commented Jan 13, 2022

Thanks for the template. On your colleague article he uses the last part of the commit for the tracking of other issues.
The Resolves: #123 at my work are Fix: #123, but we put it in the title, like: Fix: #123 - Title: Summary, imperative, ...

Do you consider that a bad practice?

@mihaigalos
Copy link

Suggest lint of commit message for meeting rules (1st letter uppercase, no full-stop at end, etc.). Nice work!

@gwd
Copy link

gwd commented Jan 13, 2022

This is mostly about the style; the content description is pretty vague.

My internal "template" for a good commit message looks like this:

  1. Explain what's the current situation
  2. Explain why that's a problem
  3. Explain how this patch fixes the problem
  4. Anything else needed to understand the patch (e.g,. alternate solutions, links to issue numbers, &c)

Then the job of a reviewer is simply verification: Is #1 true? Is the problem in #2 actually a problem? Does #3 fix the problem, and does the patch actually do #3?

@lisawolderiksen
Copy link
Author

Thanks, everyone, for the comments and feedback!

@drjasonharrison and @rjray: Yes, you both are correct. There was a missing space in the first item of the numbered list. I've corrected it now. Thanks!

@manav148 and @rany2: Thanks for suggesting commands for Mac and "anywhere" to create the gitmessage file and configure Git to use it. Great stuff. πŸ˜„

@ryankearney: You are absolutely correct about the character limits of 50/72 for title/message strictly speaking being off by one. @DervishD is also correct; I prefer it that way and I'm not very concerned about breaking a line a bit early because of it. πŸ˜‡ I'll probably update the gist so the last # is at the last char mark, since this will probably make more sense to most people. (My own .gitmessage in my dotfile-repo remains unchanged, however πŸ˜‰)

@joelparkerhenderson: Thanks for the link to your commit template! Yours is actually a template, since it includes text that will be part of the commit message. I think the prompts of "Why: " and "How:" are especially useful.

@marcelarie: Good question. I think one major benefit of including the issue tracker ID in the title is that it makes it a lot easier to see when looking at git log outputs + it possibly simplifies some kind of automation based on commit titles. I wouldn't put it there myself, as the issue tracker IDs are more "secondary" info for the work I usually do. The issue tracking stuff is more temporary than the code itself so we choose to include it at the end of the message. Another problem for me would be the 50 characters limit, I don't think I would be able to fit all I wanted to say after myteam-1234: . Those 50 chars are few and precious. πŸ˜„

@mihaigalos: I like the suggestion of linting the commit messages - do you have any suggestion on how to do it in practice?

@gwd: Those are excellent questions to answer in the commit message. Especially the focus on the current situation (which in most cases I think are part of the "why do we do this", but can be easily forgotten in the description of "why").

@mihaigalos
Copy link

@lisawolderiksen, check out commitlint.
For more generic linting (not only limited to the commit message), see pre-commit.

@lisawolderiksen
Copy link
Author

@mihaigalos Thanks!

@BenjaminEngeset
Copy link

@lisawolderiksen

Thank you for sharing! We are in a situation where commits and pull requests are spammed with lacking information. This is truly helpful!

@jpluimers
Copy link

Thanks for the great work, not just the template: also separating most of the documentation out to a markdown file so the actual template still is manageable in the editor.

A few ideas for improvement:

  • add an additional file .gitmessage containing the actual template
  • add additional files for common shells (sh on Linux/BSD/... and cmd or PowerShell on Windows) that generate the .gitmessage file (I can help with the Windows side)
  • add a few more fields in the template like (indirectly via @mihaigalos) https://www.conventionalcommits.org/ and what @joelparkerhenderson has in their template (for instance tracking, see, sponsored by)

@devdrops
Copy link

devdrops commented Nov 9, 2022

Thank you very much @lisawolderiksen! Just FYI, the original site reference for this template has changed to https://cbea.ms/git-commit/ (though the old link still redirects to it πŸ˜‰)

Also: it's worth mentioning that, in order for this template to work as expected, the commit.cleanup config must be strip. Otherwise, the comments will not be ignored.

@lisawolderiksen
Copy link
Author

Thank you very much @lisawolderiksen! Just FYI, the original site reference for this template has changed to https://cbea.ms/git-commit/ (though the old link still redirects to it πŸ˜‰)

Also: it's worth mentioning that, in order for this template to work as expected, the commit.cleanup config must be strip. Otherwise, the comments will not be ignored.

Thanks for the heads up, @devdrops ! Fixed the URLs now. :)

Regarding the commit.cleanup config: Ah. Did not know that! Since the default is strip, I'll hope that people who've changed it themselves will know this and make templates that fit their setup. πŸ˜‡ But I'll include a sentence or two about it to be sure. :)

@joelparkerhenderson
Copy link

Thanks @devdrops. I didn't know that either. I've added a usage note about strip to my template at https://github.com/joelparkerhenderson/git-commit-template

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment