14 December 2012

Git: Invalid revision range 0000000000000000000000000000000000000000..*, or how to get the root of a new branch in a hook

When commits are pushed to a Git repository, Git calls the update hook with "oldrev" and "newrev" which determine the range of commits being pushed. However, when a new branch is pushed, oldrev is "0000..0000", which makes it impossible to call, for example, "git rev-list $oldrev..$newrev" or "git diff $oldrev..$newrev", because these would throw the "Invalid revision range 0000000000000000000000000000000000000000..*" error as explained here.

The task in these cases is to use, instead of oldrev, the commit that is the root of the new branch, which is the commit reachable from newrev but not from any of the other heads. Although there are a number of suggestions as to how to get this, I have found what I think is a simpler solution. In Perl, I use
if($oldrev eq "0000000000000000000000000000000000000000"){
$oldrev = `git rev-list $newrev --not --branches | tail -n 1`;
$oldrev =~ s/\s$//;
$oldrev .= "^";
$oldrev now references the parent of the earliest commit reachable from the new head only (git rev-list lists commit objects in reverse chronological order). Then, one can use
my @filestocheck = split(/\s/,
`git diff $oldrev..$newrev --name-only --no-color`
to get the list of files modified by the push.