How to include git hooks in a repository AND still personalize your machine

April 6, 2010

In my new job as Director of Engineering at 25Lux.com, I’ve been dealing with a lot of the infrastructure parts of development that I mostly glossed over before because I always worked at a company that had everything set up for me.  It’s a good chance to think about in what kind of environment I’d really like to develop.

It turns out that big part of my answer involves automating everything.  Part of my reasoning is that our team is very small now, so the more we automate, the more we can concentrate on just development.  Another part of my reasoning is that I’ve read a lot about continuous deployment lately and many of the principles like decreasing the time between developing a hypothesis and learning your answer make sense and can only be achieved through extensive automation.

To that end, I’ve decided that all the developers should have some common git hooks in their repositories that will do things like run tests, etc.  Moreover, since we’ll be spending a lot of time developing these hook scripts, I’d like them to be backed up and versioned as well – i.e. also in the repository.

Therefore, my first step was to create a folder in the repository called /git_hooks/ and symlink /.git/hooks -> /git_hooks/.  This way, any changes we make to the hooks will be automatically applied across all the developers’ machines.

However, this has a downside in that everyone’s hooks become the same and they are unable to add their own (I, for example, might like to add a spell checker to my commit comments, but that would be annoying if someone didn’t like it).  To solve that problem, I created a /git_hooks/personal/ directory which behaves just like the normal /.git/hooks/ directory, and any hooks a developer adds in there get executed as part of the common hook.  Here’s the code I used as the base of all of our common hooks to make it work:

#!/bin/sh

# Check if the individual developer has his own hook
CMD_NAME=`basename $0`
if [ -f $GIT_DIR/hooks/personal/$CMD_NAME ]
then
  # If so, run it. $@ passes all the command line arguments passed to this function
  # If the personal hook fails, fail this one as well
  if ! $GIT_DIR/hooks/personal/$CMD_NAME $@
  then
    echo "User hook '$CMD_NAME' failed"
    exit 1
  fi
fi

exit 0

Finally, if any developer does decide to add their own hooks in /git_hooks/personal/, they should be sure to add a line containing “/git_hooks/personal/*[^.sample]” to the end of their /.git/info/exclude file so that git will ignore their customizations.

You can download this at http://gist.github.com/357538.

Advertisement

Leave a Reply

Fill in your details below or click an icon to log in:

Gravatar
WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Connecting to %s

Follow

Get every new post delivered to your Inbox.