blog/ Multiple branches using git-svn

I've recently switched to using git for source control, after svk screwed up a merge on me. Unfortunately, I'm still interacting with a Subversion repository until we convert entirely to git.

One thing that git does really well is merge, so naturally when I need to backport something from our devel tree to our stable release tree, I want to use git. Unfortunately, git-svn doesn't seem to handle branches nicely. Or, maybe it does and I'm just missing something. At any rate, I could check out using git-svn, but pushing the changes back to the branch seemed to break, so I had to hack something. Here's how I got multiple branches working.

UPDATE: Bart has found a better way of doing this. You should follow his instructions instead.

Edit: Bart pointed out that I should mention which version of git this works with, since there are usually 3 releases by the time you've eaten breakfast. Accordingly, git --version says git version 1.5.2.rc3.29.gfd985-dirty and git-svn --version says git-svn version 1.5.2.rc3.29.gfd985-dirty (svn 1.4.2)

First, clone the SVN repo with:

git-svn clone svn+ssh://your-server/home/svn/project-name/trunk -r NNNN project-name.git

where NNNN is some relatively recent revision, unless you like waiting forever for git-svn to sync. Make sure that the revision number you pick is actually on trunk -- don't just choose an arbitrary number in the past. Don't bother trying to pull branches with the -b argument at this point -- if that worked, we wouldn't be doing this.

Then, cd into project-name.git and:

git-svn rebase

to pull in everything from your NNNN revision to date.

Now you've got a working git repo that you can mangle at will, and recommit to svn with

git-svn dcommit

(There are some problems, namely that git-svn seems to get confused about ancestry if your local git branching gets complex, but we'll ignore that for now.)

Now, we want to add a second remote branch to our local git. To do this, edit your .git/config file. You've probably got soemthing like this in there:

[svn-remote "svn"]
    url = svn+ssh://your-server/home/svn/project-name/trunk
    fetch = :refs/remotes/git-svn

To track a second branch (for this example, it's "branches/3.4.x"), you want to add:

[svn-remote "svn34"]
    url = svn+ssh://your-server/home/svn/project-name/branches/3.4.x
    fetch = :refs/remotes/git-svn-3.4

You're just adding a new svn-remote stanza with a new svn-remote name, url, and fetch target.

Next, we want to pull that branch:

git-svn fetch svn34  -r MMMM

Again, pick for the MMMM revision a value that's a) somewhat recent, or you'll wait forever, and b) actually on the branch you want to retrieve.

Now, 'git branch -a' should show a new remote branch named git-svn-3.4. You don't want to mess with this remote branch, so we'll want a local master to edit and/or branch from:

git checkout git-svn-3.4
git checkout -b master-3.4.x

Now we've got a new master-3.4.x that can be used for git-svn rebase and dcommit just as your old master could. From here, cherry-pick the patches you want to backport to your branch, and then dcommit them back to svn.