June 18, 2012

GitHub has the ability to check commits before they're merged, but what if you wanted to receive the commit diffs by email so that you knew when they actually made them into your main branch? The Ruby script git-commit-notifier helps fill this purpose, and you can take advantage of GitHub's post-receive hooks and use a Sinatra server to receive notifications such as the following via HTTP POST requests:


Example
So how would you integrate git-commit-notifier with GitHub? First you need to clone the branch on the host that can receive these POST requests. Because GitHub sends a post-receive hook for each merge, you can often receive multiple web requests being sent to your Sinatra server. The naive way would be to launch the script within the POST command (i.e. %x in Ruby), but using this approach requires any operation you perform to be completed before the HTTP connection is closed.

require 'rubygems'
require 'json'
require 'sinatra'

post '/' do
if params[:payload]
   push = JSON.parse(params[:payload])
 print "JSON response: #{push.inspect}"
end

system("/home/myrepo/merge_repo.sh")
end
The script that would perform the merge_repo.sh task would then be something of the following:
cd /home/myrepo
git fetch github
# Sends diffs between our branch and origin/master
CURRENT_HASH=`git log HEAD -1 --pretty=%H`
NEW_HASH=`git log origin/master -1 --pretty=%H`
# git merge will actually be a fast-forward
git merge origin
git log --no-merges --pretty=format:"%P %H" $CURRENT_HASH..$NEW_HASH | awk '{print "e
cho " $0 " refs/heads/master | git-commit-notifier /usr/local/config/git-commit-notifier.yml"}' | sh
git checkout master
exit 0
The basic approach fetches the branch (assuming it's located on 'github'), pipes the changes listed by the parent and git hash into using the git-commit-notifier script before merging the branch. Assuming the upstream branch is simply an ancestor of the current branch, the merging should be a fast-forward.

If you plan on mirroring the repository (i.e. via Gitosis), you could setup a post-receive hook that would be configured to send diffs each time they were merged.

while read oldrev newrev ref
do
if [ "$REFSPEC" == "refs/heads/master" ]; then
echo "$oldrev $newrev $ref" | git-commit-notifier  /usr/local/config/git-commit-notifier.yml
fi
done


blog comments powered by Disqus