(This article is incomplete and in progress.)

Origin

You administer a subversion repository that is a hub of collaboration for developers, and you fancy git. You dream of a better tomorrow.

Destination

You administer a subversion repository that automatically pushes all commits to, and therefore holds a subset of, a git-svn repository and, from there, to gitolite. Developers collaborate via either repository, and changes made through git are pushed to subversion using git-svn. Your dreams are well on their way to coming true.

Preparation

You have shell access to your code server, where git, git-svn, and gitolite are already installed. You have a fair bit of storage space available to hold all the git-svn reference maps.

Journey

SVN_PATH
a local file:// path to your subversion repository.
SVN_URI
the canonical http:, ssh: or svn: URI to your subversion repository.
GITSVN_PATH
a local path to an empty directory that is not shared.

Create and initialize a git repository that is going to receive changes directly from subversion:

$ cd GITSVN_PATH
$ git init
$ git svn init --stdlayout --rewrite-root=SVN_URI SVN_PATH

Create a new text file at GITSVN_PATH/.git/authors.txt containing one line per user, similar to this:

svn_user_name = Full Name <email@address>
joshua = Joshua Tacoma <joshua@yellowseed.org>

Make sure the authors file will always be used by adding this setting to GITSVN_PATH/.git/config:

[svn]
        authorsfile = .git/authors.txt

Finally, you are ready to give the computer some heavy work!

$ git svn fetch

Oh dear, was your mighty server brought to its knees by a little git-svn fetch? Yeah, so was mine. You’ll have to import the history in smaller chunks:

$ git svn fetch --revision 1:1000 &&
> git svn fetch --revision 1000:2000 &&
> git svn fetch --revision 2000:3000

You may notice this repository is pretty darned big, so now is a good time to mention:

Beware the git-gc command’s --aggressive option! (Don’t use it!)

GITOLITE_NAME
the name of the new repository in gitolite.
GITOLITE_URI
the public URI of the new repository e.g. gitosis@code:GITOLITE_NAME.git

Configure a new gitolite repository and make sure that a subversion post-commit hook will be able to push changes into it. Your gitolite.conf file should include lines like this:

@subversion       = the accounts that process svn commit hooks
@devs             = yourself and all the other developers

repo GITOLITE_NAME
     RW           = @subversion
     RW+ develop/ = @devs
     RW+ feature/ = @devs
     RW+ release/ = @devs
     RW+ hotfix/  = @devs
     RW+ support/ = @devs
     R            = @all

Add GITOLITE_URI as a remote in the git-svn repository:

$ git remote add origin GITOLITE_URI

Change GITSVN_PATH/.git/config so that the [remote “origin”] section looks like this:

[remote "origin"]
        url = GITOLITE_URI
	fetch = +refs/remotes/*:refs/remotes/origin/*
	push = refs/remotes/*:refs/heads/*

The following commands, executed within GITSVN_PATH will fetch the latest commits from subversion and then push everything to gitolite:

$ git svn fetch &&
> git push origin

Create/modify SVN_PATH/hooks/post-commit. Here is a perfectly functional example:

#!/bin/bash
cd GITSVN_PATH && git svn fetch --quiet && git push --quiet origin

If the post-commit command produces any output whatsoever, subversion clients will be confused about whether the commit succeeded, resulting in false conflicts!

(TODO…)