Andy Delcambre
Software Engineer at GitHub. Ruby programmer. Photographer.

Automated Time Tracking using git06 Feb 2008

My git workflow usually involves creating a branch for the feature I am working on (or just a bugfix branch) making commits there until the feature is done, then merging back into my master branch and pushing to our subversion server. I started thinking about the fact that if I could simply keep track of all of the time that I spent in the branch it would be a fairly good approximation of the time spent working on the feature. I did successfully implement this and it works fairly well with a few small exceptions.

First, I am using a post-checkout hook in git which is not implemented until version 1.5.4 which is currently at rc4. Luckily the git-checkout script is just a shell script so it was trivial to backport support for the hook. Second, I am using zsh to implement some of the features, and I am not sure if similar things could be accomplished with bash or tcsh.

This technique has three main parts: recording when you enter and leave a branch, calculating the total time spent in the branch, and a system to automatically switch you out of a branch after a few minutes of inactivity.

First the time logging feature. This is the part that uses the post-checkout hook to function. Basically, every time you do a checkout of a branch, the post-checkout script records a timestamp in a log file for the branch you are entering and the branch you are leaving. After a while you build up a log of timestamps in the file. It looks something like this (I standardised again the ISO8601 date format). The post-checkout script is available here

in 2008-01-25T12:36:36-08:00
out 2008-01-25T12:42:43-08:00
in 2008-01-25T13:20:41-08:00
out 2008-01-25T13:29:57-08:00
in 2008-01-25T15:13:47-08:00
out 2008-01-25T15:15:08-08:00
in 2008-01-25T16:56:03-08:00
out 2008-01-25T16:58:09-08:00

Now that you have this time log of the time you spent in the branch, you can calculate how long the feature took you to implement. I used a commit-msg hook to do this. This adds the amount of time the commit took you directly to the commit message. I created this as a script in /usr/local/bin called git-time so you can also run it manually, (the hook is just a symlink). The script also reset the time log file (with just one entry for the current time). The script is a available here

When you commit it adds the time to the commit message:

commit 7e739f01377806be8b93ef181fc99c54058bcd89
Author: Andy Delcambre <andy.delcambre@planetargon.com>
Date:   Wed Feb 6 14:17:57 2008 -0800

    test commit
    This commit took 1.35 hours

The last piece ensures that you don’t simply keep the branch checked out all the time and that you switch back to master when you aren’t actually working in the branch. It uses the zsh feature of having a shell TMOUT (which triggers a SIGALRM after the number of seconds specified elapsed), then trapping the alarm and switching to the master branch if you are in a git repository and not already in the master branch.

Here is what you should add to your .zshrc:

TRAPALRM () {
	# Used to do time tracking for git commits
	if [[ -d .git ]]; then
		if [[ `git branch | grep '*' | awk '{print $2}'` != 'master' ]]; then
			git co master
		fi
	fi
}

export TMOUT=300

It seems to work fairly well, but there are a few issues. First, the time log can get screwed up: you can put your laptop to sleep while still in a branch. This results in having a greatly exagerated time in the commit message. I always check with git log to see if the time estimate is approximately accurate, and just reset and recommit (with a greatly under-exaggerated time). There is also always the extra few minutes of work that get done after doing the actual commit (resolving the todo item, merging and committing to the subversion server, etc) so I usually add a bit. But overall it works fairly well for me. Are the other tools that you use to help you with tracking your time?