UPDATE: See my blog post about GitZilla - git-bugzilla integration done right. The stuff below is bitrotten and outdated now.
There's always SCMBug, but you can cook your own Git-Bugzilla integration very easily. SCMBug's fine, but it's a lot of code if all you want is simple cross-linking between Git, Bugzilla and Trac (btw - GitPlugin for Trac would throw up an error unless you have at least *two* commits in your repository - talk about undocumented easter bugs!).
Anyhoo - here's what I want :
1. Git should disallow any commit where the commit message does not have a bug number.
2. Git should add a comment to the corresponding bug on a commit, mentioning the author, the Trac changeset link, the commit message and the list of files which changed.
And here's the code to do it. First, the post-receive hook :
#!/usr/bin/perl -w use strict; # A hook script which integrates with bugzilla. It looks for bug IDs in # commit messages and adds the commit message as well as a link to the # changeset as a comment on the bug. # This program is released under the terms of the GNU General Public License # version 2. A copy of the license may be obtained by emailing the author, # or at http://www.gnu.org/licenses/old-licenses/gpl-2.0.txt # # The absolute lack of warranty and other disclaimers as per the license # apply. # # Copyright 2008, Devendra Gera. All rights reserved. # # Author : Devendra Gera### user configurable section # The bugzilla has contains the server, username and password for the targeted # bugzilla installation. There's NO 'http://' in the server line. my $bugzilla = { server => "10.147.251.90/bugzilla", user => "demonuser", password => "daemonuserspassword", }; # __PATH__ and __REVISION__ are replaced in $browser->{changeset} and # $browser->{revision} to get the changeset and revision URLs respectively. my $browser = { changeset => "http://10.147.251.90/projname/changeset/__REVISION__", revision => "http://10.147.251.90/projname/browser/__PATH__?rev=__REVISION__", }; # The bug_regex should extract the bug id from the commit message and place # it in $1 my $bug_regex = 'bug #(\d+)'; ##### End user configurable section use WWW::Bugzilla; my $input = <>; chomp $input; my ($oldrev, $newrev, $refname) = split /\s+/, $input; my $commit_msg = `git-whatchanged $oldrev..$newrev`; # prepare the changeset URL my $changeset_url = $browser->{ changeset }; $changeset_url =~ s/__REVISION__/$newrev/g; # author my ($author) = ( $commit_msg =~ /^Author:\s+(.*)$/m ); # files my @filelist = grep ( /^:/, split( /\n/, $commit_msg ) ); # prepare comment $commit_msg =~ s/^.*?Date://s; # eat everything till the Date: heder $commit_msg =~ s/^.*?\n//m; # eat the date line completely $commit_msg =~ s/^:.*?$//mg; # eat the file list from the msg. chomp $commit_msg; my ($bug_number) = ( $commit_msg =~ /$bug_regex/ ); my $comment = <<END_COMMENT; ------------------------------------ changeset $newrev [ $changeset_url ] by $author : $commit_msg ------------------------------------ Files changed : END_COMMENT $comment .= join("", @filelist) . "\n"; my $bz = WWW::Bugzilla->new( server => $bugzilla->{ server }, email => $bugzilla->{ user }, password => $bugzilla->{ password }, bug_number => $bug_number ); die "cannot connect to bugzilla" unless defined $bz; $bz->additional_comments( $comment ); $bz->commit;
And here's the update hook :
#!/usr/bin/perl -w
use strict;
my $refname = shift;
my $oldrev = shift;
my $newrev = shift;
my $commit_msg = `git-whatchanged $oldrev..$newrev`;
# check if the commit message contains a bug number
if($commit_msg !~ /bug #\d+/) {
exit -1;
}
exit 0;
The TODO :
1. Push every configurable thing to git's config file and access it via git-config.
2. Code cleanups. One definition of the bug regex (which is hardcoded in the update for now).
edit : the here doc in the code was causing a problem with formatting, eating up some of the code. Fixed now.