Git hooks

From git documentation:

Hooks are little scripts you can place in $GIT_DIR/hooks directory to trigger action at certain points. When git-init is run, a handful example hooks are copied in the hooks directory of the new repository, but by default they are all disabled. To enable a hook, make it executable with chmod +x.

If you take a look at your .git/hooks folder you will probably see a bunch of hooks created by default. In my current version of git all my hooks have a .sample extension. To make a hook executable you must remove .sample and make it executable. If you don’t want to remove the default example you can create a new file without .sample.

What will our hook do

We want our hook to run all our unit tests before a commit is made. If any test fails then the commit will not be applied and the commiter will be notified about what happened.

Hooks are usually written in shell but they can be written in any language. We are going to use PHP for our hook.

How will our hook do it

To run our hook before commiting we will use the pre-commit hook. We need to create a file and name it pre-commit in our .git/hooks folder and make it executable.

In this example it is assumed that you are using PHPUnit with a test suite file for your project.

This is going to be the content of our file:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
#!/usr/bin/php
<?php
// Hook configuration
$project = 'My Project';
$testSuiteFile = '/home/myself/www/project/tests/My_Project.php';

// Tell the commiter what the hook is doing
echo PHP_EOL;
echo '>> Starting unit tests'.PHP_EOL;

// Execute project unit tests
exec('phpunit '.$testSuiteFile, $output, $returnCode);

// if the build failed, output a summary and fail
if ($returnCode !== 0)
{
    // find the line with the summary; this might not be the last
    while (($minimalTestSummary = array_pop($output)) !== null)
    {
        if (strpos($minimalTestSummary, 'Tests:') !== false)
        {
            break;
        }
    }

    // output the status and abort the commit
    echo '>> Test suite for '.$project.' failed:'.PHP_EOL;
    echo $minimalTestSummary;
    echo chr(27).'[0m'.PHP_EOL; // disable colors and add a line break
    echo PHP_EOL;
    exit(1);
}

echo '>> All tests for '.$project.' passed.'.PHP_EOL;
echo PHP_EOL;
exit(0);

This example is strongly based on Mike’s gist on github: https://gist.github.com/975252.

[ git  linux  php  ]
Using Gerrit with MySQL
Using Gerrit for better collaboration on git projects
Hooking your github project to Travis-CI
Changing your default name and e-mail on git
Git hook to run code static analysis