git-svn gotcha

Posted by craig

I was having problems with the following setup the other day:

[remote deveoper] <===> [shared git repo] <===> [me] <===> [client's svn repo]

So my remote developer and I push and pull to/from the shared git repo, and then I sync changes to and from the client’s svn repo using git-svn.
h1. Problem My problem is, when I am ready to merge changes from my local master branch to trunk-local, if I do a “git merge master” and then try to issue any git-svn commands I get the following errors:
======================
$ git merge master
Updating d88106e..77b86ae
Fast forward
 community/pom.xml |    2 +-
 1 files changed, 1 insertions(+), 1 deletions(-)

$ git svn dcommit
Can't call method "full_url" on an undefined value at
/usr/local/git/libexec/git-core/git-svn line 425.

$ git svn rebase
Unable to determine upstream SVN information from working tree history
======================

The only way I’ve seem to be able to remedy this is if I add the “subtree” merge strategy to the merge command:

git merge -s subtree master

Then git-svn doesn’t get confused about it’s repo, but when you look at the repo using gitk, you see something like:

[trunk-local]--[remotes/trunk]  Merge branch 'master' into trunk-local
| \
|  \
|    [master]--[remotes/origin/master]  "last master commit msg" 
|    |
|    |
|  /
/

When I use the normal merge strategy then gitk shows all branches at the same level, but git-svn is of course b0rked.

Solution

I tried asking a few people on #git (freenode irc channel for git) for help, but the problem was a bit too involved to explain on irc and have someon follow along, so instead what I did was I asked on the official git mailing list (git@vger.kernel.org) and I got an answer almost immediately from Björn Steinbrink with a solution that seems to work just great! His input was to use --no-ff when merging my changes into the svn tracking branch (trunk-local). Here is his explanation:

The original merge you did ended up as a fast-forward, ie. no merge commit was created. I guess that your history is so, that somehow the remotes/trunk stuff is reachable through the second parent of some merge commit that exists in your history. But git-svn uses—first-parent to find its upstream, so it cannot find that in your scenario. I guess it’s best if you use “git merge—no-ff master” to force the creation of a merge commit. Subtree happens to work because it implies—no-ff, but I’m not sure whether there might be downsides to using the subtree strategy, so I’d rather go with the explicit—no-ff and the normal merge strategies.

Hopes this helps other’s in the same situation as I was in. Thanks Björn Steinbrink


Comments

Leave a response

Comment