Sunday, October 27, 2013

More git-svn Woes

I was pretty happy with myself after I figured out to always use git-svn with the --prefix configuration. However, as +Johan Herland foretold, this stopped working after Git 1.8.3.2. Or to be precise, the convenient branch checkout/tracking mechanism stopped working.

So while you could do this before (imagine a fresh git-svn clone with --prefix=mirror/):

>git branch -a                                        
* master
  remotes/mirror/trunk #this is a svn remote

> git checkout trunk  
Branch trunk set up to track remote branch trunk from mirror.

Now, after upgrading Git past Git 1.8.3.2, you'll get this instead:
> git checkout trunk
error: pathspec 'trunk' did not match any file(s) known to git.

Even if you try doing it more explicitly:

>git checkout -tb trunk mirror/trunk
fatal: Cannot setup tracking information; starting point 'mirror/trunk' is not a branch.

Strangely enough, git branch earlier told us that this is a branch. We can even check out the head of it, albeit in detached mode:

> git checkout mirror/trunk       
Note: checking out 'mirror/trunk'.
You are in 'detached HEAD' state.[...]

So how can we check out this branch then? This is how:

>git checkout -b trunk refs/remotes/mirror/trunk
Switched to a new branch 'trunk'

Now, I think it should be tracking everything already, git-svn-wise, so you can do git svn dcommit and git svn rebase right away. 

If you want the technical reasoning for why this is the case now, I've quoted bits of Johan's post here (hyperlinks added by me), but I do recommend reading the whole thing:
Prior to v1.8.3.2 this still sort-of works (as you observe below),
because the code fails to realize the remote is invalid, and falls back
to setting branch.feat-bar.remote = "." (i.e. the current repo). This
might seem like an ok practice until you realize that a "git push" back
to that invalid upstream would happily overwrite
refs/remotes/(mirror/)feat-bar, and thus break git-svn's internal state.  
This bug was fixed in v1.8.3.2, more specifically 41c21f22 (branch.c:
Validate tracking branches with refspecs instead of refs/remotes/*),
and you can read more about the rationale in that commit message. 
So, how long do we have to put up with this? Well, by the looks of things, the default prefix thing won't be addressed before Git 1.9 or 2.0 (some time in 2014?), and I'm not even sure the easy tracking stuff will be fixed then at all.