DEV Community

Cover image for Keeping Git Commit Messages Consistent with a Custom Template
Timothy Merritt
Timothy Merritt

Posted on • Updated on

Keeping Git Commit Messages Consistent with a Custom Template

XKCD comic 1296 displaying increasingly less informative git commit messages over the course of a project

xkcd on git commit messages

The ability to write consistent git commit messages is a skill that will serve both you and any team you’re working with well in the long run. If you often find yourself struggling to come up with a decent message format, or you’re unable to decipher what it was you were doing when looking back through old commits, this little fix might help. And the best part is it’s extremely easy to implement.

You can set a file to act as a commit message template through git’s global configuration. I tend to follow the conventional commits format, which makes it easy to decide how to format your messages, and keeps things organized across all your commits. Chris Beams also has a great article on this topic.

First, create a .txt file in a directory of your choice that will act as the template. I’ll assume you’re using the terminal for the process.

touch commit-conventions.txt
Enter fullscreen mode Exit fullscreen mode

Open the .txt file with the editor of your choice. Git will ignore lines that begin with a # or ; by default, so we’ll use those to make a template of ignored lines that only you will see when you’re making commits.

Note: By default, git allows both # and ; as comment characters for configuration files, but you can set a character of your choice with git config --global core.commentChar '#', substituting # with your preferred character.

You can put whatever you want in your template, but here’s mine as an example:

# ----------------------------------------------------------
# Header - type(scope): Brief description
# ----------------------------------------------------------
#    * feat             A new feature - SemVar PATCH
#    * fix              A bug fix - SemVar MINOR
#    * BREAKING CHANGE  Breaking API change - SemVar MAJOR
#    * docs             Change to documentation only
#    * style            Change to style (whitespace, etc.)
#    * refactor         Change not related to a bug or feat
#    * perf             Change that affects performance
#    * test             Change that adds/modifies tests
#    * build            Change to build system
#    * ci               Change to CI pipeline/workflow
#    * chore            General tooling/config/min refactor
# ----------------------------------------------------------


# ----------------------------------------------------------
# Body - More description, if necessary
# ----------------------------------------------------------
#    * Motivation behind changes, more detail into how
#      functionality might be affected, etc.
# ----------------------------------------------------------


# ----------------------------------------------------------
# Footer - Associated issues, PRs, etc.
# ----------------------------------------------------------
#    * Ex: Resolves Issue #207, see PR #15, etc.
# ----------------------------------------------------------


Enter fullscreen mode Exit fullscreen mode

To add the template to your global git config is enter the following:

git config --global commit.template path/to/your/file.txt
Enter fullscreen mode Exit fullscreen mode

Now whenever you’re making a commit, instead of the typical git commit -m "A brief commit message", just enter git commit to open your default editor with the template in place. You’ll automatically have a guide to choose conventions from to create a structured message. For example:

# ----------------------------------------------------------
# Header - type(scope): Brief description
# ----------------------------------------------------------
#    * feat             A new feature - SemVar PATCH
#    * fix              A bug fix - SemVar MINOR
#    * BREAKING CHANGE  Breaking API change - SemVar MAJOR
#    * docs             Change to documentation only
#    * style            Change to style (whitespace, etc.)
#    * refactor         Change not related to a bug or feat
#    * perf             Change that affects performance
#    * test             Change that adds/modifies tests
#    * build            Change to build system
#    * ci               Change to CI pipeline/workflow
#    * chore            General tooling/config/min refactor
# ----------------------------------------------------------
docs: Update README with contributing instructions

# ----------------------------------------------------------
# Body - More detailed description, if necessary
# ----------------------------------------------------------
#   * Motivation behind changes, more detail into how 
# functionality might be affected, etc.
# ----------------------------------------------------------
Adds a CONTRIBUTING.md with PR best practices, code style 
guide, and code of conduct for contributors.

# ----------------------------------------------------------
# Footer - Associated issues, PRs, etc.
# ----------------------------------------------------------
#   * Ex: Resolves Issue #207, see PR #15, etc.
# ----------------------------------------------------------
Closes #9
Enter fullscreen mode Exit fullscreen mode

The “header” of the commit message notes the type of the commit as docs and a brief description that does not exceed 60 characters to ensure readability (the commented lines are 60 characters long and act as guides for when to use a line break). The “body” optionally elaborates on the changes made, and the “footer” optionally notes any issue/PR the commit is related to. The final message will simply look like this:

docs: Update README with contributing instructions

Adds a CONTRIBUTING.md with PR best practices, code style 
guide, and code of conduct for contributors.

Closes #9
Enter fullscreen mode Exit fullscreen mode

For more specifics on the convention formatting or how it works with semantic versioning, see my git configuration. If it's too confusing or overly complex for your use cases, just simplify as needed.

If you use Vim or Neovim, and you want to speed up the process even more, you can add this to your git config:

# Neovim
git config --global core.editor=nvim +16 -c 'startinsert'

# Vim
git config --global core.editor "vim +16 +startinsert"
Enter fullscreen mode Exit fullscreen mode

This sets the default editor to Neovim (or Vim), and places the cursor on line 16 in Insert Mode as soon the editor opens. Now whenever you’re committing, when you type git commit, Neovim opens the template, places your cursor, and accepts typing input immediately. Also note that you can still use git commit -m "Your message" exactly as you did before, but the configuration will default to the template setup when you just type git commit.

See more tips for configuring your editor with git here

Setting up this template has saved me countless time and frustration, and makes it so much easier to track my commits since all my repos use the same global commit format. You can get much more creative with git defaults and complex githooks, but this is a great way to solve a common problem for most developers.


timmybytes banner

If you enjoyed this...

Top comments (19)

Collapse
 
haxnet profile image
HaxNet

Thanks for letting me know about this. I use git here and there and like the feature of template.

git config --global core.editor=nvim +14 -c 'startinsert' didn't work for me

I use arch, not sure if that's the reason, but for anyone having trouble with this.
My fix

git config --global core.editor 'vim +14 +startinsert'

cheers

Collapse
 
timmybytes profile image
Timothy Merritt

Thanks for pointing this out, @haxnet . I've edited the article to include Neovim and Vim configurations, with links to more info!

Collapse
 
joelrozen profile image
Joel Rozen

Conventional Commits node package also does this for you but gives you a nice interactive cli asking you to choose / enter descriptions etc.

Collapse
 
timmybytes profile image
Timothy Merritt

Thanks for this! It seems really slick. For anyone else interested, the project is called commitlint.

Collapse
 
michaelcurrin profile image
Michael Currin

Can I suggest updating your example to match the style that is actually recommended on Conventional Commits site which you linked to.

-(docs): Update README with contributing instructions
+docs: Update README with contributing instructions
Enter fullscreen mode Exit fullscreen mode

Remove the brackets. Brackets are for scope.

Based on the link, if you were working on adding a language to the docs, you could add scope.

docs(lang): Add Polish section
Enter fullscreen mode Exit fullscreen mode

I think the scope is also useful for module. For example if you have foo and bar in src directory, you would do feat(foo) to show the commits are scoped to the foo module.

The scope can be whatever you want but the advice is your team needs to agree on it and stick to it.

Collapse
 
timmybytes profile image
Timothy Merritt

Thanks for mentioning this. When I originally started using the convention, I didn't use the scope/module designator, since for many smaller projects it can be overkill. I just kept the parentheses around the type for aesthetics, but I see how that could be confusing for someone adopting the conventional method (and/or make the template incompatible with other conventional commit tools). I've updated the article to include these changes, and also added more info on structuring a commit message in my git configuration.

Cheers!

Collapse
 
michaelcurrin profile image
Michael Currin

That linked page looks good.

That's a lot of dotfiles. Here are just a few of mine github.com/MichaelCurrin/dotfiles

Collapse
 
michaelcurrin profile image
Michael Currin

Happy to help :)

Also you could turn your help message into a shell alias or a bookmarked page / gist so you can read it anytime without committing.

Collapse
 
michaelcurrin profile image
Michael Currin

Something useful to add to your available type is chore. Such as deleting or renaming a file. Or changing a config like .gitignore which relates more to the repo itself than your application's build flow.

I started using build for only build-related configs - like a package.json or lint config file.

Collapse
 
timmybytes profile image
Timothy Merritt

I actually had already been using chore, but forgot to add it here! The article's been updated to include it. Thanks for mentioning it!

Collapse
 
michaelcurrin profile image
Michael Currin

You're welcome.

I'd appreciate if you have a look at my extension which doesn't let you choose a semantic message, it writes one for you.

github.com/MichaelCurrin/auto-comm...

Collapse
 
hatemhosny profile image
Hatem Hosny

There is also a nice vscode extension for conventional commits

Collapse
 
pepellou profile image
♜ Pepe Doval

Nice, thanks for sharing!

Just a minor typo: the git-config to set line 14 on vim should say core.editor instead of core-editor.

Collapse
 
timmybytes profile image
Timothy Merritt

Thanks for catching that! It’s been edited and updated. Cheers!

Collapse
 
phongduong profile image
Phong Duong

Thank you for sharing

Collapse
 
lavinj87 profile image
Jorge Lavin

Thanks, really useful.

You may want to add that the comment character is configurable. In my case is ; so I modified the template accordingly.

Collapse
 
timmybytes profile image
Timothy Merritt

Thanks! I've edited to include info on configuring the comment character. From git's documentation, both the # and ; characters are valid by default, but in case anyone wants theirs to be "🤫" or something, there is info on how to set it now!

Collapse
 
petroskoulianos profile image
Petros Koulianos

This is great 😎. I was thinking if i was able to do such a think. It is very useful for dev teams working with git - issues - branches.
Thanks for sharing Timothy.

Collapse
 
murkrage profile image
Mike Ekkel

I like the idea of creating a commit message template :). Might end up proposing this to the teams at my company!