Git Commit Templates

Sunday is when I typically write about my Book of the Week. However, in the past two weeks I have been so involved with other activities that I just have not found the time to finish reading “Visualizing Quaternions” by Andrew Hanson. Therefore I am going to write about something else today: a useful feature of Git that people rarely take advantage of, at least in my experience.

I present to you a short tutorial on commit message templates.

My Use-Case

I use GitHub as the host for PHP Mode, but I also use the site as a bug and issue tracker. If I make a commit that addresses an issue on GitHub then I like to document that in the commit message, for example:

commit 16cb0c09a773340f4f3dcf6d093376dcd7a3a49b
Author: Eric James Michael Ritz <lobbyjones@gmail.com>
Date:   Sat Aug 17 03:46:54 2013 -0400

    Fix an error about php-extra-constants being void

    It is possible for us to byte-compile PHP Mode and receive an error
    about php-extra-constants being void as a variable.  We can correct
    this by using the ‘autoload’ magic comment to make sure Emacs
    evaluates the defcustom call that defines the variable.

    GitHub-Issue: 120

The last line in the message tells me the specific issue behind the patch. Sometimes regressions happen and re-introduce bugs. When that happens and someone re-opens a previously closed issue I always begin be reviewing the existing patches related to that issue. Thanks to the issue reference in the commit message I can begin this review like so:

$ git log --patch --reverse --grep="GitHub-Issue: 120"

That will show me the history of commits related to the issue, starting with the oldest.

Computer programmers are inherently lazy people and I am no exception. On projects such as PHP Mode most of my commits deal with specific GitHub issues. And so I don’t like typing GitHub-Issue: over and over. Fortunately Git provides a way to automate that.

Enter Commit Templates

Git stores data in the .git/ sub-directory of a project. In my local copy of PHP Mode I have a text file named .git/info/template with the following contents:

GitHub-Issue:

The documentation for git-commit describes the --template option, or -t for short. The option lets you give Git a file to use as the template for the commit, meaning Git will use the contents of that file as the initial draft for the commit. That means instead of typing GitHub-Issue: every time I can do this:

$ git commit --template=".git/info/template"

That will open my editor to write the commit message with GitHub-Issue: already there. But that command requires more typing, which is exactly what I’m trying to lazily avoid! Thankfully, once again, Git functionality comes to rescue me from the tediousness of typing twenty characters.

Git supports a lot of configuration variables. The important one for the purpose of this article is commit.template. If I configure it to point to a file then git-commit will automatically use that file as the template for commit messages. For example:

$ git config --local commit.template ".git/info/template"

# Now running this command...
$ git commit

# ...is the same as if I had run this.
$ git commit --template=".git/info/template"

Now my template will appear in almost all new commit messages, with two common exceptions:

  1. Git will not use the template if I provide a commit message on the command-line via git commit -m "...".

  2. Git will also ignore the template if I create the commit message from an existing file (-F) or an existing commit (-c and -C).

There are some other circumstances where Git will not use a commit template, but the two situations above are the exceptions that pop up most often in my workflow.

Conclusion

That is the gist of creating and using a commit template. One reason I put my templates in the .git/info/ directory is that I rarely share them, i.e. I do not commit them for other developers to use. But there is nothing to stop you from doing so; it can be a useful way to help build and enforce some stylistic guidelines for commit messages on a project. You can even use a single template for every Git repository by using git config --global commit.template path/to/template, which individual repositories can then override with a local value for commit.template.

So if you tend to repeat something in commit messages you may want to consider using a template. It is a nice exercise in laziness and a good safeguard against forgetting to include information you want to include in (almost) all commits.

Advertisements

3 thoughts on “Git Commit Templates

  1. Since you use emacs, I was wondering if you use magit.

    If so, I found this solution for using a template through magit-log-edit-mode-hook.

    https://github.com/rawsyntax/emacs.d/blob/master/eric/magit-commit-template.el

    Ideally, I would like to be able to configure the git commit template by emacs mode, say drupal-mode, for all my Drupal projects, which use Jira ticket numbers and some other template for my personal projects.

    I’ll share more, if I get anything interesting figured out.

    1. I used Magit years ago and was a big fan of it. Honestly I don’t remember exactly why I stopped using it; even though I haven’t kept up with its development I still often recommend to programmers that they check out Magit if they’re using both Emacs and Git.

      Thanks for sharing the link to magit-commit-template.el, it looks useful. I also like your idea about configuring templates based on the current major mode. Just off the top of my head I can sort of envision how to implement that as an extension for Emacs’ vc-mode, which could be nice for other SCM tools that provide similar template functionality.

      Definitely let me know if you start hacking on any code to implement anything like that, for Magit or otherwise. I may also experiment with implementations of the idea in my own spare time.

Add Your Thoughts

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s