Notifying your development team when a git commit is made

My last writeup, looked at how to write a pre-commit hook for your git repository that would not allow you to submit broken PHP code. This time, I’ll show you how to use the .git/hooks/post-commit hook in order to notify all of your development members when a commit has been made successfully. It is very important to understand the environment that git runs in. In my current development setup, only trusted developers get access to git and the helper scripts. By the time I have a hijacked rogue developer account messing with our repositories, I have much bigger problems on my hand. This is why I have setup a common place on my server to store helper scripts and other utilities that any of our developers can use. This is by no means the NSA brand secure way of doing things, but that discussion is a whole other topic.

Before we get into the actual code, there are a couple of things that are worth noting. No matter where you push your commit from within the source tree, the hooks will always run from the root of the repository. Let’s say we have a project hosted at “/path/to/my/project/development/”, then we can test this by looking for a directory “/path/to/my/project/development/.git/”. If that checks out then we are in the right place. Now that we have our path information, we know that if we run “git commit -a” from “/path/to/my/project/development/html/assets/css/”, any hook run by git will actually run from “/path/to/my/project/development/”. This is important because it allows us to write one single server wide post commit script, instead of having to write a brand new hook for every new repository.

As I stated before on my machines, I always have a directory of system wide helper scripts. For this application I use have a folder mgh off of the root of the machine, and underneath are several other directories. For this example we only need to look at “/mgh/bin/git-post-commit”. This script must be executable by your developers or their user group. Here is the source for my system wide post commit script:

#/usr/bin/php
<?php
 // Define our commit timestamp format
 $CommitWhen    = date('l jS \\of F Y h:i:s A');

 //  Look for the git commit message file
 // ( which still exists at this point in the commit process )
 // under the directory this script is run from.
 $TryFile       = $_SERVER['PWD'] . '/.git/COMMIT_EDITMSG';

 // If the commit message does not exist, then dump a no message found.
 $CommitMessage = (file_exists($TryFile)) ? file_get_contents($TryFile) : 'No Commit Message Found';

 // Define our formatted mail body
$body =<<< END_BODY
Source Control Commit Successfully Issued by user {$_ENV['USER']}.

Commited from: {$_SERVER['PWD']}
Commited On: {$CommitWhen}

+----- Commit Message -----+
{$CommitMessage}
END_BODY;

 // Define our email subject (this also tells what user actually did the commit)
 $Subject = "Source Commit From {$_ENV['USER']}";

 // A list of email addresses of the developers we wish to notify
 $Notifications = array('tcrider@mghus.com',
                        'timcrider@gmail.com',
                        'dev2@developer.com',
                        'dev3@developer.com');
 $devCount = count($Notifications);

 // Emails Away!
 for ($i = 0; $i < $devCount; $i++)
    mail($Notifications[$i], $Subject, $body);

As you can see, this script knows that all git commits come from the root of the repository, and can easily determine if the git commit message can be fetched. Once we have the message, we can send it out to all of our developers. Since we now have a single git-post-commit script, all we have to do is call it from within the hook and we're done. Here is how my .git/hooks/post-commit looks:

#!/bin/bash
#
# An example hook script that is called after a successful
# commit is made.
#
# To enable this hook, make this file executable.
/mgh/bin/git-post-commit

That is all there is to it. Now all of the developers on my system can be notified whenever a commit has been made to a repository we want to monitor. This of course is a very simple example, and could easily be extended to add many other features that open up new ways to improve your source control process. You should also remember, that the post-commit hooks can call multiple scripts. So adding in things like packaging, backups, logging, or anything else you can think of should be easy to do.

I hope this helps, and as always comments and suggestions are welcome.