Time Taken - A git time tracker

published 06 Aug 2009 by Mark Percival
filed under: Code

If git is such an integral part of your day job, and you work on the clock, wouldn’t it be nice to combine tracking time with your git commits? Tracking time can be difficult when you have such a different system. I still use a timer to keep track of what project I’m working on, but inherently there’s a disconnect from the code. If you’ve got more technically savvy clients that like to keep track of the git log, combining time tracking also allows them to get an idea or how long something takes and set future expectations.

But where do we log the time. You could quickly look at a days logs and tally up the time, but with all that data you should be able to mine it for a little more insight than just billing. This is where Google Spreadsheets comes into play. If you weren’t already aware, Google Spreadsheets now allows you to create a html form for your spreadsheet and let people enter information into it from any website. While this is a cool feature in and of itself, it has the sideeffect of letting of simple ‘get’ or ‘post’ information from anywhere: the command line, curl, net/http in ruby. By now, where I’m going with this is pretty obvious.

A post-receive/post-commit hook – what I want is to be able to add time taken to a git message like this:

 git commit -a -m "Added a user method for activation [TT 30m]" 

Then when I send it up, or commit it(depending on your setup), I should see log entry for that time show up in my Google spreadsheet.

Here’s the post-commit script

#!/usr/bin/ruby -w

# Time Taken
# A ridiculously simple way to track time in git using Google Spreadsheets
# Copyright: 2009 Mark Percival - SquarePush LLC - squarepush.com
# License: MIT

# Installation
# 1. Create Google spreadsheet and update configuration
# 2. Copy this file to .git/hooks/post-commit in your project
# 3. chmod +x .git/hooks/post-commit

# Usage:
# git commit -a -m "Updated to rails 2.3.2 [TT 30m]"
# git commit -a -m "WTF? No 'goto' in Ruby? [TT 2.5h]"
# git commit -a -m "Switched back to Merb [tt 1.25H]"  <--case insesitive

# How to set this up
#
# Start by building a spreadsheet with the following columns
# Client | Project | Minutes | Message | Commit | Committed By
#
# Then create a form for it and go look at it
# Inside the form source you'll see the post URI
# It should look something like this
# http://spreadsheets.google.com/a/mpercival.com/viewform?hl=en&formkey=dDVWVTZvYmg45ExeVEp0Z0RlN3lCcWc6MA..
# This is all we need to talk with google - The rest should be pretty self explanatory

# Configuration
# The only stuff you need to worry about
# ------------------------------------------------------------------------
form_post_uri="http://spreadsheets.google.com/a/mpercival.com/formResponse?formkey=dDV2VTZFYmg3ME7PVEp240RlN3lCcWc6MA.."
client='Github'
project='Speed improvements'
committer='Mark Percival'
# ------------------------------------------------------------------------



last_log = `git log --pretty=oneline -n1`
last_log.strip.match(/^([0-9a-z]+)\s(.+)$/m)

commit = $1
message = $2

if match = message.match(/\[TT\s(.+)(.)\]/i) 
  time = match[1]
  unit = match[2].downcase
  case unit
  when 'm'
    minutes = time.to_i 
  when 'h'
    minutes = (time.to_f * 60).ceil
  else
    puts "Error logging Time Taken \"#{match[0]}\" \n"
  end
end

if minutes
  # Require only if we have minutes to log, since this is the slowest part
  require 'net/http'
  require 'uri'
  require 'cgi'
  client = CGI.escape(client)
  project = CGI.escape(project)
  message = CGI.escape(message)
  committer = CGI.escape(committer)
  puts "Logging #{time} #{unit == 'h' ? 'hour' : 'minute'}#{time.to_s == '1' ? '' : 's'} to #{client} - #{project} \n"
  begin
    Net::HTTP.get(URI.parse(
    "#{form_post_uri}&entry.0.single=#{client}&entry.1.single=#{project}&entry.2.single=#{minutes}&entry.3.single=#{message}&entry.4.single=#{commit}&entry.5.single=#{committer}"))
  rescue Exception => e 
    puts '*' * 50
    puts "There was an error updating the spreadsheet - #{e.message}\n"
    puts '*' * 50    
  end
end

# Fin
exit(0)


blog comments powered by Disqus