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.
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 <firstname.lastname@example.org> 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:
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:
Git will not use the template if I provide a commit message on the command-line via
git commit -m "...".
Git will also ignore the template if I create the commit message from an existing file (
-F) or an existing commit (
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.
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
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.