My Take on the Git Commit Logger

I've recently migrated this blog, and the older posts might not yet be satisfactorily cleaned up. Apologies for the temporary mess.

Almost all the work that I do on my computer that is worth doing goes through a Git repository. My Git commits are therefore a useful indication of what I’ve accomplished each day, except they are scattered across many directories.

When I saw that Brett Terpstra created a script to make a log of all his Git commits, I saw the solution to my problem. Terpstra has an implementation that scans a list of repositories once per day, filters certain kinds of commits, and exports them in different kinds of formats. That’s more power than I needed, so I wrote my own script. The main difference is that where Terpstra’s script is run by cron once per day and goes out to fetch commits, my script is run after every commit and pushes the information to the log.

The script is run using the magic of Git hooks, in this case, post-commit. Any script named post-commit in the .git/hooks directory will be called after each commit.

Here is the script (also as a Gist):

<span class=“c1”>#!/usr/bin/env ruby</span>

<span class=“c1”># Write git commit messages to a log file</span> <span class=“c1”># </span> <span class=“c1”># Lincoln A. Mullen | lincoln@lincolnmullen.com | http://lincolnmullen.com</span> <span class=“c1”># MIT License <http://lmullen.mit-license.org/></span> <span class=“c1”>#</span> <span class=“c1”># You will have to install the git gem for this to work:</span> <span class=“c1”># gem install git</span> <span class=“c1”>#</span> <span class=“c1”># Name this file 'post-commit' and drop it in the directory '.git/hooks' in</span> <span class=“c1”># any repository that you want to log. Make sure the file is executable. You</span> <span class=“c1”># can also add this to your git templates, which will put it in every new</span> <span class=“c1”># repository or to existing repositories by re-running git init. </span> <span class=“c1”># </span> <span class=“c1”># A commit message in the log should look this this:</span> <span class=“c1”># 2013-07-26-11-25-55 [repository:branch] First line of commit message</span>

<span class=“nb”>require</span> <span class=“s2”>“git”</span>

<span class=“n”>log_file</span> <span class=“o”>=</span> <span class=“s2”>“/home/lmullen/todo/time-use.txt”</span> <span class=“n”>repo</span> <span class=“o”>=</span> <span class=“no”>Git</span><span class=“p”>.</span><span class=“nf”>open</span><span class=“p”>(</span><span class=“no”>Dir</span><span class=“p”>.</span><span class=“nf”>pwd</span><span class=“p”>)</span> <span class=“n”>repo_name</span> <span class=“o”>=</span> <span class=“no”>Dir</span><span class=“p”>.</span><span class=“nf”>pwd</span><span class=“p”>[</span><span class=“sr”>%r{[</span><span class=“se”>.-\w</span><span class=“sr”>]+$}</span><span class=“p”>]</span> <span class=“c1”># top directory</span> <span class=“n”>date</span> <span class=“o”>=</span> <span class=“n”>repo</span><span class=“p”>.</span><span class=“nf”>log</span><span class=“p”>.</span><span class=“nf”>first</span><span class=“p”>.</span><span class=“nf”>date</span><span class=“p”>.</span><span class=“nf”>strftime</span><span class=“p”>(</span><span class=“s2”>“%Y-%m-%d-%H-%M-%S”</span><span class=“p”>)</span> <span class=“c1”># format date</span> <span class=“n”>message</span> <span class=“o”>=</span> <span class=“n”>repo</span><span class=“p”>.</span><span class=“nf”>log</span><span class=“p”>.</span><span class=“nf”>first</span><span class=“p”>.</span><span class=“nf”>message</span><span class=“p”>.</span><span class=“nf”>lines</span><span class=“p”>.</span><span class=“nf”>first</span><span class=“p”>.</span><span class=“nf”>strip</span> <span class=“c1”># just first line</span> <span class=“n”>branch</span> <span class=“o”>=</span> <span class=“n”>repo</span><span class=“p”>.</span><span class=“nf”>log</span><span class=“p”>.</span><span class=“nf”>first</span><span class=“p”>.</span><span class=“nf”>name</span> <span class=“no”>File</span><span class=“p”>.</span><span class=“nf”>open</span><span class=“p”>(</span><span class=“n”>log_file</span><span class=“p”>,</span> <span class=“s2”>“a”</span><span class=“p”>)</span> <span class=“k”>do</span> <span class=“o”>|</span><span class=“n”>log</span><span class=“o”>|</span>
<span class=“n”>log</span><span class=“p”>.</span><span class=“nf”>puts</span> <span class=“s2”>”</span><span class=“si”>#{</span><span class=“n”>date</span><span class=“si”>}</span><span class=“s2”> [</span><span class=“si”>#{</span><span class=“n”>repo_name</span><span class=“si”>}</span><span class=“s2”>:</span><span class=“si”>#{</span><span class=“n”>branch</span><span class=“si”>}</span><span class=“s2”>] </span><span class=“si”>#{</span><span class=“n”>message</span><span class=“si”>}</span><span class=“s2”>”</span>
<span class=“k”>end</span>

You can drop that following script into the hooks directory of each repository that you want to watch. Or, learning from Tim Pope, you can create a Git templates directory which will be added to repositories when you run git init.
git config –global init.templatedir <span class=“s1”>'~/.git_template'</span>
mkdir -p ~/.git_template/hooks