Git Hooks

Git hooks are sim­i­lar to SVN hooks; you can exe­cute a script at a point in the Git rou­tine. Git hooks are both local and serv­er-side. The local hooks per­tain to local activ­i­ties, like com­mit­ting, merg­ing, check­ing out, etc. The serv­er-side hooks deal with receiv­ing push­es from a local client.

The scripts that Git hooks exe­cute are stored in the .git/hooks direc­to­ry of your project. In every repos­i­to­ry there are a col­lec­tion of sam­ple hooks that you can rename and use as inspi­ra­tion for your own.

The scripts can be in any lan­guage that sup­port exe­cutable scripts. The sam­ples are most­ly shell scripts, but you can use Perl, Ruby, Python, or some­thing else that is famil­iar to you.

Here are all the hooks avail­able in Git:

  • pre-commit
  • prepare-commit-msg
  • commit-msg
  • post-commit
  • applypatch-msg
  • pre-applypatch
  • post-applypath
  • pre-rebase
  • post-rewrite
  • post-checkout
  • post-merge
  • pre-push
  • pre-receive
  • update
  • post-receive

Local Git Hooks #

Local Git hooks reside in the .git/hooks direc­to­ry and are not treat­ed as project files. They are not tracked in the Index and because of that they are not includ­ed when some­one clones a repos­i­to­ry. They are tru­ly just local.

Because of this there are some lim­i­ta­tions to keep in mind while work­ing with Git hooks. First and fore­most: local hooks are not a reli­able way to enforce poli­cies, like a com­mit mes­sage struc­ture. And, because you are unable to include the con­tents of the .git/hooks direc­to­ry in ver­sion con­trol, you will need to con­sid­er a way to share hooks that you’d like your team to use. 

Here are the local hooks:

  • pre-commit
  • prepare-commit-msg
  • commit-msg
  • post-commit
  • applypatch-msg
  • pre-applypatch
  • post-applypath
  • pre-rebase
  • post-rewrite
  • post-checkout
  • post-merge
  • pre-push

Serv­er-side Hooks #

Serv­er-side hooks are set up to kick off scripts when a typ­i­cal remote repos­i­to­ry actions takes place. 

There are only three serv­er-side hooks:

  • pre-receive
  • update
  • post-receive
  • They all oper­ate around when the serv­er receives a git-push from a client. These are reli­able meth­ods for enforc­ing some sort of repos­i­to­ry or stan­dard. You can run checks, kick of an inte­gra­tion script, test­ing, etc. 

Imple­ment­ing a Git Hook #

For our exam­ple we’re going to imple­ment a local hook that will dis­play a mes­sage before each com­mit, remind­ing us to push our com­mits to the remote repository.

The set­up for this mes­sage will be to use the post-com­mit hook. This hook is trig­gered after each suc­cess­ful com­mit. For our imple­men­ta­tion, we want the hook to trig­ger and dis­play a mes­sage for us.

My usu­al first step would be to open the sam­ple hook (hookname.sample) but for post-com­mit there isn’t a sam­ple hook in the default instal­la­tions of Git.

But let’s open anoth­er one just to see what it looks like. The hooks are locat­ed in .git/hooks inside of your project direc­to­ry. I like to use Vim to edit, but you can open this is any edi­tor you’d like.

$ vim .git/hooks/pre-commit.sample

We see that this hook is writ­ten as bash script. Inside of it we can put rules for what should hap­pen before a com­mit is cre­at­ed. This file has a lot of extra stuff in it, includ­ing com­ments to explain what the hook does and how to enable it (by renam­ing it, remov­ing the .sample portion.

But let’s quit out of that and start work­ing on our own hook.

Cre­at­ing the Hook File

We need to first cre­ate a new file called post-commit (no file exten­sion nec­es­sary in .git/hooks.

We are going to use Ruby as our script­ing lan­guage. Remem­ber, Git Hooks can use any exe­cutable script. I like Ruby so we’ll use that.

Add this code to the new file:

	#!/usr/local/bin
	puts "======================="
	puts "Please remember to push your commits!"
	puts "======================="

With the code in place, we can then save the hook file and set it as executable.

$ chmod +x post-commit

And now let’s test it by mak­ing a change to our project and cre­at­ing a com­mit. If every­thing is set up prop­er­ly, any­time you cre­ate a com­mit in this repos­i­to­ry, you will see that mes­sage appear!

Post-Push Hooks #

If want to have hooks that are trig­gered serv­er side but you use a ser­vice like Github, then you can take advan­tage of the Github imple­men­ta­tion. Almost all host­ed Git ser­vices have some­thing similar.

  • Go to your repos­i­to­ry at Github
  • Choose Set­tings
  • Choose Web­hooks

Any hooks you had here will be trig­gered using the post-receive hook. The trig­ger will hap­pen after Github suc­cess­ful­ly receives a push. You can do any­thing here, like hit a URL of a web ser­vice that trig­gers some­thing on your serv­er (like a build or deploy­ment or some­thing else).