Sunday, April 29, 2012

Rebuilding Git Integration Environment

About ten days ago, after getting to the office, I found that my home box that I use as the primary integration machine was not responding. Later in the day, wife calls from home saying that the box is dead and does not even respond to the power button.

So until I had a chance to look at the box and resurrect it, I had to build the Git Integration Environment elsewhere. As Linus famously said once, only wimps use backup and real men just upload their important stuff and let the rest of the world mirror it ;-). All of my integration branches are pushed to multiple places, and one of the public repositories even have all of the topic branches, so it is just the matter of fetching them back. Other people could even try to imitate what I do by following this procedure.

First, grab all the branches I had in the primary box from the mirror:

$ git init git.git
$ cd git.git
$ git fetch --update-head-ok git://github.com/gitster/git refs/*:refs/*
$ git reset --hard master

Unfortunately, GitHub adds garbage refs to my repository that I didn't push; I can eradicate them like this, but this step is not strictly necessary:

$ for x in $(git for-each-ref --format='%(refname)' refs/pull/)
  do
    git update-ref -d $x
  done

After this, I can start building Git from tips of topic branches as usual, but my usual procedure is to make heavy use of helper scripts in the 'todo' branch that is checked out in the Meta directory (e.g. I run Meta/Make instead of make from the top-level, and that Make script is in the 'todo' branch).

$ git init Meta
$ (cd Meta && git pull git://git.kernel.org/pub/scm/git/git.git todo:master)
$ Meta/Make test install

Among the helper scripts on the 'todo' branch (and checked out in the Meta directory is Reintegrate script.  This is used to maintain redo-jch.sh and redo-pu.sh scripts I rebuild 'jch' and 'pu' branches with.

$ Meta/Reintegrate master..jch >Meta/redo-jch.sh
$ Meta/Reintegrate jch..pu >Meta/redo-pu.sh
$ chmod +x Meta/redo-*.sh

What is still missing after the above is the contents of the rerere database. This mechanism remembers the manual conflict resolution I had to perform when I built the integration branches (i.e. 'next', 'pu' and 'jch') earlier. Luckily, there is a script to do so in contrib/ since Sep 2008:

$ PATH=$PATH:. contrib/rerere-train.sh master..pu

This populates the rerere database by learning from the merge commits between 'master' and 'pu' branches, so after that, I can try rebuilding 'pu', like this:

$ git checkout master^0 ;# I am not really rebuilding--just "try rebuilding"
$ Meta/redo-jch.sh ;# replay all the merges that should go to the jch branch
$ Meta/redo-pu.sh ;# and then the merges to the pu branch on top
$ git diff HEAD pu ;# there should be no differences

After this, I can look at individual topics, decide which topics are worthy to be merged to 'next' or 'master', and advance tips of these integration branches with appropriate invocations of the git merge commands.

By the way, it turns out that the breakage was a failed power supply. I ordered one from NewEgg, which arrived early last week, but I procrastinated until this morning to replace it. After the necessary hardware swap,  running the above procedure again to get the environment back was more or less trivial.

So, it's Baaack ;-)

No comments: