Ten Steps to Custom Git Hooks

This past weekend, I participated (along with Flatiron students Adam Waxman, David Manaster, Max Jacobson, and Sarah Duve) in a hackathon sponsored by Jawbone, Tumblr, the Clinton Foundation, and Ace Hotel. It was an awesome event where we worked with the soon-to-be-public Jawbone API to create hacks that encourage healthy behavior using sleep data from the Jawbone UP bands, as a way to create behavioral change around social determinants of chronic illness (in this case sleep).

I’ll write more in depth about this hackathon later, and about the project Sarah, Max, and I created, where we wrote a custom pre-commit git hook which allows or blocks commits to a project based on a threshold of user sleep data parsed form the Jawbone UP API. However, I wanted to describe how to make custom git hooks in this post, as a fun little hack that can also provide more powerful functionalities (such as not allowing people to commit their code if they haven’t slept enough) based on how you design it.

Before I start, I wanted to describe a little more about a hook and why they are cool and important. In programming, there is a concept of hooking into a certain moment in time in your program. A common one that Ruby developers might be familiar with is the initialize method, which allows you to hook into the moment in time when a new instance of a class is created and set certain attributes, or set other programs in motion.

Git also has hooks, and I’m going to describe here how you can set them yourself.

Step 1

Create a new directory by running $ mkdir wellthisisfun or whatever you want to call it

Step 2

Set it up as a git repo by calling git init in your directory.

Step 3

Here you could push the repo up to github, but it’s not necessary to create a git hook. What you do need to do is cd into .git by doing .git . You won’t see it when you call ls on your directory, because it’s a dotfile, which means it’s hidden. However, after you initalize a git repo (step 2), it’s there in your directory, whether or not it’s on github.

Step 4

You can ls your .git directory. You’ll see some interesting stuff that’s fun to explore here, such as config , HEAD , info , and objects . If nothing else, it’s an interesting way to start learning more about what git is and how it works. In this step, we want to get into the hook folder by calling $ cd hooks

Step 5

Open up your hooks. I’d suggest using Sublime here, so you can do something like $ subl . and look at all of them.

Step 6

Cool! Here are your git hooks. You can see the moments in time you can hook into through git here. In our project, we played around with the pre-commit.sample hook, but you can browse through all of these, and figure out what the best tool is for what you want to do (or which sandbox interests you the most).

Step 7

Setting your Ruby environment is necessary if you want to be able to write this hook in Ruby. Put this at the top of your code: #!/usr/bin/env ruby

Step 8

Write your hook. You can write stuff like puts "hello there #{ENV["USER"]}" to say your name, puts Time.now to put the current time, or things like exit(1) to make it exit the program. Play around. You can require gems (since they have global scope on your computer, this works), and do all sorts of Rubyesque/Railslike stuff, such as making calls to APIs, etc.

Step 9

Make your hook executable. This requires either one or two steps. The first is to take away the “.sample”“ at the end of your file name (e.g. ”“pre-commit.sample”). If you decide to do this by saving over your pre-commit.sample file, your file is already executable, so that’s it. If you decide to just add a new file to hooks called something like pre-commit (or whatever moment you want to hook into), you’ll need to run this in the command line $ chmod a+x YOURFILE (e.g. $ chmod ax pre-commit ). The point of this step is to make your computer able to execute the file. Also, just a note – make sure to copy the same format of the filename as the existing hook samples. For example, pre-commit will work, since there is a pre-commit.sample hook, but precommit will not work.

Step 10

Test it out. Cd to the top of your directory, create a new file by doing $ touch myfile.rb or make changes to a file, run git add . , commit it by running git commit -am 'my message' , and you should see your hook executed when you do.

I think this is fun way to explore the concept of hooks, to think more deeply about git, and to conceptualize what you can do by hooking into those moments in git and linking them to APIs, other processes you are running, etc. Please let me know if you have any questions or thoughts in the comments!