Chomper Stomping
jQuery/JavaScript/CSS 3/HTML 5, Java/PHP/Python/ActionScript, Git, Chrome/Firefox Extensions, Wordpress/Game/iPhone App Development and other random techie tidbits I've collected



project management

November 18, 2010

Making Git show post-receive e-mails as an HTML color formatted diff

octocat


I wanted git to send me an e-mail with a color formatted HTML diff view of pushes/commits whenever the remote server received a push. After some digging I found that I could accomplish this using the post-receive email hooks in combination with Pygment’s command line tools (using Python).

Prerequisites:

I will assume for this post that you have Git, Python and Pygments installed. It’s been months since I installed Pygments, and I honestly can’t remember *anything* about installing it, which means it was probably pretty straightforward and easy. You probably can just do this from your shell:

sudo easy_install Pygments

Making your Git repo send colored diff e-mails:

1. Setting up the post-receive hook

a. post-receive

The first thing you will need to do is configure your post-receive hook:

/git/your-repo.git/hooks/post-receive

In the hooks directory (cd /git/your-repo.git/hooks/) there will probably already be a “post-receive.example” file. Just copy it and rename it post-receive.

This file is basically a shell script. It is run after your repo gets a push and is updated. It is passed in 3 arguments: old revision hash, new revision hash, refname

All you really need to put in this file is the following line:

. ~/git-core/contrib/hooks/post-receive-email

What this does is calls another shell script “post-receive-email” and passes along the arguments (I think).

I’m pretty sure you could specify other shell scripts in the same way at this point if you wanted to.

b. post-receive-email

Now make the file you referenced from the post-receive file:

Move to your global hooks directory (the other one you were just in was specific to just that one repository, this one is the global hooks dir):

cd ~/git-core/contrib/hooks/

Create a file called post-receive-email. This is a shell script, but DON’T put “.sh” on the end.

Now, place the following code in that file (or, better yet, here’s the file):

I’ll try and point out some of the relevant portions of this script:

generate_email_header() (line 198):

This is the header of the e-mail, including the subject as well as the first few lines of the e-mail.

You may notice some variables here. ${emailprefix}, $projectdesc, etc. I’ll talk a little about these later on.

Basically, what you need to know here is that if you want to change the e-mail subject or the beginning content of the e-mail, you do that here. You *could* hard code the recipients here, but don’t. We’ll talk more about recipients later.

generate_email_footer() (line 219):

This is the footer of the e-mail.

Notice that I placed a line here that tells you which files are causing these e-mails to be sent. I highly recommend keeping this line so that whenever you want to change anything about the e-mail, the e-mail itself tells you everything you need to know about doing so.

show_new_revisions() (line 605):

This is triggered if someone pushes up new revisions that have not ever been pushed up before. This way each code change will only be shown in one e-mail ever. This is the part that generates the actual diff itself and this is probably the single more important part oft his blog post. Lines 635 through 638:

git show -C --pretty=format:"committer: %cn%ncomments: %N%n%s%n%b" $onerev > gitlog.txt
export PYTHONPATH='/usr/local/lib/python2.4/site-packages'
pygmentize -O noclasses=True -f html -l diff gitlog.txt
pygmentize -O noclasses=True -f html -l diff -o gitlogemail.html gitlog.txt

Let’s break it down line by line:

1. This is the actual git diff. If you just plop this down in your command line right now (minus the > gitlog.txt part) and replace $onerev with a sha1 hash from your log, you’ll see a “preview” of how your e-mail will theoretically look. Here’s some code for you to try to see what I’m talking about, do the following in your shell:

git log

Copy one of the sha1 hashes shown the log, then…

git show -C --pretty=format:"committer: %cn%ncomments: %N%n%s%n%b"

(so, for example, and don’t try using this exact line because you won’t have my sha1 hash in your repo so it won’t work):

git show -C --pretty=format:"committer: %cn%ncomments: %N%n%s%n%b" 583038808efbde6fef4eb2e92dd2a920ba714eed

(hit “q” to get out of the diff view this throws you into)

If you don’t like anything about this diff view, you can change it by editing the format:”….” part. See the git-show page in the git manual for details.

LOGBEGIN (line 656):

This is a constant (it’s counterpart is LOGEND on the next line). The contents here will be used in the script in various places. It’s content is placed before the diff to help separate the diff from the rest of the e-mail.

recipients (line 676):

You *could* hard-code e-mail recipients here, but DON’T, we’ll once again talk about this in just a few moments…

emailprefix (line679):

emailprefix=$(git config hooks.emailprefix || echo '[SCM] ')

This specifies the text you want showing up right before the subject of the e-mail. It pulls in a setting from your gitconfig (again, we’ll talk about this in a moment) but it also specifies a default in case you don’t have one set. I make all my e-mails subject lines prepend with [GIT] so I know it’s an automated git e-mail at a glance.

custom_showrev (line 680):

This line currently doesn’t do what it looks like it does. At first line it appears that you can set your diff settings here, but this is actually unused at the moment. I was trying to make it so you could set your git-show settings in the git config, but I was having trouble getting it to work and gave up because I had bigger better fish to fry… So, don’t be fooled into thinking you can change this line and have your e-mails be effected.

2. Setting your git config options

In the post-receive-email file, there were several variables that I kept saying I would talk about later. Now’s the time!

We are going to set the variables in your git-config. I’m not 100% sure, but I suspect that this will allow you to have different settings per repository.

The way you do this is:

Move to your repository’s home directory:

cd /git/your-repo.git/hooks/

At this point, you can dive right in and make new config settings, or you can list current settings. List current settings like this:

git config --list

To add new config settings:

git config --add blah.blah true

or

git config --add blah.blah "that is soo true dude"

or, better yet, just pop open the .git/config file in a text editor (git config -e) and add lines like this:


[blah]
blah = that is soo true dude

hooks.mailinglist

Whatever you put here will go in the “To:” field. (This is who the e-mail will be sent to).

git config --add hooks.mailinglist "ralphie@gmail.com, frank@gmail.com, steve@gmail.com"

Don’t be fooled by the similarly named “hooks.announcelist” which, as far as I can tell, does nothing (theres a few lines of code that may use this if it isn’t empty, but I haven’t looked into this very far. Don’t set it and it won’t negatively effect anything. If you do set it, you may get unexpected results).

hooks.emailprefix

This is the text that will be inserted before the subject line. I like to set mine to [GIT] so I know it’s an auto generated git e-mail by just glancing at the subject. If you don’t set it, it defaults to [SCM].

git config --add hooks.emailprefix=[GIT]

Testing

Ok, at this point, you should be all good to go. Make a code changes, commit, push to your remote and sit back and wait on the e-mail.

Problems? I probably won’t be able to help, but I’ll try. Better to try asking on StackOverflow.com.

Good luck!



About the Author

Christopher McCulloh
E-Commerce developer at Finish Line Co-Author of HTML, XHTML and CSS All-in-one Desk Reference for Dummies Graduated from IU with a Bachelors of Media Arts and Science and a Certificate in Applied Computer Science. Tech Editor for Building Facebook Applications for Dummies and Building Websites All-in-one for Dummies 2nd Edition. Creator and maintainer of the Status-bar Calculator Firefox Extension Three years professional experience in Java E-Commerce Development and four years professional experience with PHP for a combined total of seven years professional JavaScript/HTML/CSS experience




 
 

 
logo

dynode Batch Get Item

Working a lot with node.js, dynode and dynamoDB recently. Still trying to wrap my head around it all. Had a horrible time getting dynode.batchGetItem to work. Here is the error I was getting: { name: 'AmazonError', type: 'Valid...
by Christopher McCulloh
0

 
 
mysqlerror

WP phpBB Bridge: Warning: mysql_set_charset() expects parameter 2 to be resource, boolean given

Warning: mysql_set_charset() expects parameter 2 to be resource, boolean given in wp-content/plugins/wp-phpbb-bridge/inc/widgets/wpbb_topics_widget.php on line 149 This is an error caused by the fact that the WP phpBB Bridge pl...
by Christopher McCulloh
0

 
 
 

Events Calendar Pro Nav Formatting Messed up on Empty Calendar

The Events Calendar Pro (from http://tri.be/) has a few problems. If you are trying to figure out why a calendar with no events in that month has completely screwed up header navigation, just put this line of code inside of tab...
by Christopher McCulloh
5

 

 
warning

OH SHNIKES, WE’VE BEEN HAXORED!!!

Yes. It finally happened. After… 6 years? on the web I finally got hacked. Two domains affected: http://cmcculloh.com http://hallelujahbutton.com (this also of course affected all sub-domains of cmcculloh.com, such as blo...
by Christopher McCulloh
2

 
 
blue-xl

WordPress Settings API – Adding Options to Existing Page

Adding new options to an existing page in the dashboard in wordpress can be maddening. I’ve literally spent 15+ hours dealing with this horrible API at this point. To the point where I wrote two different wrappers for it....
by Christopher McCulloh
0

 




8 Comments


  1. Thank you, this was exactly what I was looking for!
    You did an excellent job breaking down the script
    and explaining the parts in detail. Kudos for that!

    – MM.


  2. FYI,

    You can edi your git config by typing:

    git config -e

    (opens vi. “i” to “insert”(edit) the document. “esc” followed by “:q” to “quit” or “:wq” to “write”(save) and “quit”)

    You can list current configuration by typing:

    git config -l


  3. Awesome stuff! Thanks for sharing :)


  4. I’ve made some tiny adaptions to the script, enabling the revs to link to gitweb (view diff in gitweb). Maybe you should put this script on GitHub, so I (and others) could fork it?


  5. Ah, never mind, I see it’s already a Gist. Sorry! :)


  6. Leo141

    Thanks for the fine script.

    Should anyone, like me, get an error like “UnicodeDecodeError: ‘ascii’ codec can’t decode byte 0xfc in position 478: ordinal not in range(128)” because of using non-ASCII chars in their source code, they can customize the script by adding an option like “-O encoding=latin-1″ to both pygmentize commands contained in the script.


  7. Aha! Thanks for the tip! I’ll try and get around to fixing that when I get back to work next year…



Leave a Reply

Your email address will not be published. Required fields are marked *

*

You may use these HTML tags and attributes: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <strike> <strong>