Dev Blog

Git: Not Just Source Control

by Jason Diller on April 1, 2012

At FreshBooks, we really like git for our source control. Git provides us with easy branch management, reliable source control, and the commands are intuitive. But git’s usefulness isn’t limited to source control. We’ve discovered that git’s elegant interface and potent functionality make it useful for all sorts of applications.

For example, a couple of months ago our internal Jabber server was down for maintenance and the maintenance window lasted a bit longer than expected (something about Erlang packages and CentOS, I think). I was working on a project with some other developers located dozens of feet apart and we had been collaborating with each other using Jabber to save the walk to each other’s desks. With the Jabber server down, and facing the productivity hit of having to walk across the office, we did what any developer would do and worked around the problem.

Someone said, “well, we already share code using git, why not use that for messages too?” It seemed so obvious once it was put like that. It was dead simple.

We started out by setting up private message repositories on our local hosts, and a shared project message repository on a central host, then everyone cloned all of the repositories and we set about making the necessary enhancements to our systems to make use git as the transport for a proper messaging system. And then when new people join the team, they create their own messages repository as well, and clone each of the other developers’ messages repositories. Then they have to clone the project repositories. Then every developer has to clone the newbie’s personal repository before they can send him or her messages. But, git is fast, so no big deal.

Sending a message is simple:

jason@jason:~$ echo "This project is the bomb, yo" >> team_msg_01
jason@jason:~$ git add team_msg_01
jason@jason:~$ git commit -m "Message about the project being the bomb, yo"
jason@jason:~$ git push origin

Message sent!

Some people felt that four commands to send a message was too much work, so we rolled up a bit of automation:

#!/bin/sh

# gitmsg.sh
#
# usage: gitmsg recipient message
#
# sends 'message' to 'recipient' using git
# expects ~/gitmsg/recipient to exist and to be a git repository

pushd ~/gitmsg/$1
git pull origin master
#use a concatenation of the current username and timestamp for the filename
FILENAME=`whoami``date +%s`
echo message > $FILENAME
git add $FILENAME
git commit -m "New message at `date`"
git pull --rebase
git push origin master
popd

Now sending a message to the project team is a simple one-liner at the terminal prompt:

jason@jason:~$ ./gitmsg.sh sekret_project "I ate all the m&m's, sorry guys"
~/gitmsg/sekret_project ~
[master dbbe3a0] New message at Thu 29 Mar 2012 08:05:55 EDT
 1 files changed, 1 insertions(+), 0 deletions(-)
 create mode 100644 jason1333022755
Counting objects: 3, done.
Delta compression using up to 4 threads.
Compressing objects: 100% (2/2), done.
Writing objects: 100% (2/2), 305 bytes, done.
Total 2 (delta 0), reused 0 (delta 0)
Unpacking objects: 100% (2/2), done.
To ssh://gitmsgserver/git/sekret_project.git/
   d648e38..dbbe3a0  master -> master

Of course, sending messages is only half the problem, we need to display them too. Since everyone on the FreshBooks dev team always has at least one terminal window open, this part is easy, we just install git hooks to read new messages as they arrive and display them in the terminal window.

For my private messages repo, I use a local-to-my-computer bare repo that anyone can push messages to, so I need a post-receive hook to display the messages when they arrive:

#!/bin/bash
#gitmsg post-receive hook
#install in local message repos to output messages as they arrive
#

while read line 
do
   #get the range of commits passed to the hook
   START=`echo $line|cut -f1 -d ' '`
   END=`echo $line|cut -f2 -d ' '`
   commits=`git rev-list --abbrev-commit $END ^$START`
   for commit in $commits 
   do
       #get the author information from the commit
       from=`git log -n1 --format='%aN'`
       #get the list of files (messages) in the commit
       files=`git show --pretty="format:" --name-only $commit`
       #extract the contents (message) from each file
       for file in $files
       do
           message="Message from $from\n\t`git show $commit:$file`"
           #find terminals that don't look like they're running an editor
           editor_terminals=`ps -a|egrep -v "(vi|vim|emacs)\ "|grep tty.*|cut -f2 -d' '|uniq`
           non_editor_terminals=`ps -a|egrep "(vi|vim|emacs)\ "|grep tty.*|cut -f2 -d' '|uniq`
           terminals=`comm -3 <(echo $editor_terminals |tr ' ' '\n' |sort) <(echo $non_editor_terminals| tr ' ' '\n' |sort)`
           for terminal in $terminals
           do
                echo -e $message|write jason $terminal
           done
           #and pop up a growl notification
           echo -e $message|growlnotify
       done
   done
done

Of course, each developer maintains their own post-receive hooks so they can tune the notifications however they want. This is what it looks like when I send myself a message using gitmsg:

(The terminal on the left is sending the message, and the terminal on the right is receiving it.)

Screen Shot

Screen Shot

Git is really amazing. Now that it's supplanted our need for Jabber, we're thinking of using it for even more things. Our bug tracker is looking a little long in the tooth, and everyone's had enough of email so those are certainly candidates!

If you've found new uses for this great tool, share them with us in the comments!

6 Comments (add comment)

Tom says:
Apr 1/12 11:15 am

That’s pretty cool, you should hook it up to growl. That or use IRC. While I keep (several) terminal windows up at all times, I don’t typically want messages obscuring the output that I’m already using nor do I want to read messages from a terminal. That’s why I have IRC. Gchat, etc. But…I think you could very easily hook it up to growl. That would be awesome. Thanks for some ideas, good post! =)

Scott says:
Apr 1/12 12:33 pm

My post-receive hook plays this: http://www.youtube.com/watch?v=08WFI6WpnmA

Apr 2/12 12:45 pm

My post-push hook play’s Salt n’ Pepa’s “Push It”.

Travis R says:
Apr 6/12 2:59 pm

Man, this is the most ridiculous use of git I’ve ever seen. Talk about complicating something that is generally so simple.

Chris says:
Aug 23/12 4:11 am

I’d love to see how you guys work in a team with Git.
Branches/forks, etc.

PS: I also love GIT, and for anybody even remotely interested in Source Control… check out the YouTube video with Linux Trovalds talking about him creating GIT code tool from scratch! :D

Leave a Comment ( *required)

*
*

*

Search