2012/12/15: Ad-hoc sharing with git-bundle(1)

The man page for git-bundle(1) is, my opinion, not known to the extend it deserves. In the example section, it contains a step-by-step instruction for forward-synchronisation of git repositories. And it's easy! It is a single command to create a bundle and a single command to remember how far the last bundle brought you.

One application is jointly working on a set of files. You simply commit the files you want to share to a git-repository and send a bundle, for example via singed and encrypted email. When you receive a bundle back, you have proper conflict detection and merge suggestions. No need for any special cloud-synchronisation service, no set-up effort, and, since you can choose to have end-to-end encryption, you don't even have to trust your mail provider.

Pushing bundles is also a very convenient way to keep files in sync between your various machines. I use uucp to copy bundles to my laptop.

For repositories I share regularly with the same people, or those I want to have to synchronised between my various machines, I use a script like the following, which is run by a cron-job.


#!/bin/sh

FILE=`date +%s`-delta

for repo in repoFoo repoBar
        do cd ~/Working/$repo && git bundle create ~/Working/BUNDLES/$repo/$FILE GTUlastdelta..master && git tag -f GTUlastdelta && uucp -g c -C ~/Working/BUNDLES/$repo/$FILE 'path!to!my!other!machine!~/upload/gtu/myrepositories/'$repo/$FILE 
done

## repoFoo is also for Joe

if [ -f ~/Working/BUNDLES/repoFoo/$FILE ] ; then (echo "Find attached foo bundle $FILE") | mutt -e 'unset record' -s "foo bundles" -a ~/Working/BUNDLES/repoFoo/$FILE -- joe@example.com; fi
download

To collect all the incoming bundles, I use the following script.


#!/bin/sh

SOURCE=/var/spool/uucppublic/upload/gtu
MIRROR=/home/aehlig/gitmirror/

if [ "x$1" != "x" ]; then
    echo "Starting new mirror for group $1, repo $2"
    mkdir -p $MIRROR/repos/$1
    mkdir -p $MIRROR/deltas/$1/$2

    INITIAL=`cd $SOURCE/$1/$2/ && ls *-initial`
    [ -f $SOURCE/$1/$2/$INITIAL ] || (echo "Failed to find initial delta"; false) || exit 1
    echo "Absolute Delta $INITIAL"
    mv $SOURCE/$1/$2/$INITIAL $MIRROR/HERE.bundle
    (cd $MIRROR/repos/$1 && git clone $MIRROR/HERE.bundle $2)
    (cd $MIRROR/repos/$1/$2 && git checkout master)
    mv $MIRROR/HERE.bundle $MIRROR/deltas/$1/$2/$INITIAL

    exit
fi

echo "pulling new incoming deltas"

for group in `cd $MIRROR/repos && ls`; do 
    for repo in `cd $MIRROR/repos/$group && ls`; do 
        for bundle in `cd $SOURCE/$group/$repo && ls | sort`; do
            mv $SOURCE/$group/$repo/$bundle $MIRROR/HERE.bundle
            (cd $MIRROR/repos/$group/$repo && git pull)
            mv $MIRROR/HERE.bundle $MIRROR/deltas/$group/$repo/$bundle
        done
    done
done
download

By the way, the idea of collaborating via emailing version-control-system information is much older than git. In the past, I used to email rcs files. And already in 1994, Poul-Henning Kamp committed CTM to FreeBSD which allow mirroring the FreeBSD repository by receiving a few small signed emails. It is the way, I'm keeping my machines up to date—today in 2012.