views:

278

answers:

4

I'm using git-svn to work with an SVN repository. My working copies have been created using git svn clone -s http://foo.bar/myproject so that my working copy follows the default directory scheme for SVN (trunk, tags, branches).

Recently I've been working on a branch which was created using git-svn branch myremotebranch and checked-out using git checkout --track -b mybranch myremotebranch. I needed to work from multiple locations, so from the branch I git-svn dcommit-ed files to the SVN repository quite regularly.

After finishing my changes, I switched back to the master and executed a merge, committed the merge, and tried to dcommit the successful merge to the remote trunk.

It seems as though after the merge the remote tracking for the master has switched to the branch I was working on:

# git checkout master
# git merge mybranch
... (successful)
# git add .
# git commit -m '...'
# git svn dcommit
Committing to http://foo.bar/myproject/branches/myremotebranch ...
#

Is there a way I can update the master so that it's following remotes/trunk as before the merge?

I'm using git 1.7.0.5, if that's any help.

It would be useful if you could also explain why this happened, so I can avoid the problem happening again. Thanks!

Edit:

Here is my current .git/config:

[core]
    repositoryformatversion = 0
    filemode = true
    bare = false
    logallrefupdates = true
    autocrlf = false
[svn-remote "svn"]
    url = http://foo.bar/myproject
    fetch = trunk:refs/remotes/trunk
    branches = branches/*:refs/remotes/*
    tags = tags/*:refs/remotes/tags/*
[branch "mybranch"]
    remote = .
    merge = refs/remotes/myremotebranch

So it seems that the trunk is pointing to the correct place. However, switching to the branch then back to the master doesn't help; git svn dcommit in the master still tries to push to myremotebranch.

A: 

open .git/config in your working directory, then you can modify it to point the master to the remotes/trunk

sza
Seems as though the `master` actually *is* pointing to the `trunk`.
digitala
A: 

If you haven't made any commit on master, that means the git merge mybranch was a fast-forward one: master HEAD simply move to mybranch HEAD.

That could explain why the git svn dcommit pushed your changes to the SVN mybranch.
It would:

  • first update the corresponding SVN branch with the last Git mybranch commits not yet dcommitted,
  • record the merge to trunk on the SVN side
  • and then it would rebase master on the Git side (nothing to do, already there).

I don't think master hasn't change its reference, but if you have a doubt (and your working directory is clean), you could (if master is currently checked out):

git reset --hard remotes/trunk
VonC
It seems as though resetting, changing something on the master, `dcommit`ing, then re-merging so there is a conflict, fixing that conflict, then `dcommit`ing fixes the issue. Its not pleasant though.
digitala
@digitala: you mean the reset alone is not enough? The first dcommit after the reset doesn't occur on the SVN trunk?
VonC
+3  A: 

When there are no changes on trunk, git does a fast-forward merge and simply sets the local "master" branch to the commit on your branch. Git-svn doesn't know how to commit fast-forward merges back to trunk, in fact it thinks "master" now is pointing to the svn branch.

To work around this, use git merge --no-ff when merging. This will force git to create a merge commit, which can then be dcommitted to svn.

Daniel
good point on the `--no-ff`. +1
VonC
To clarify, if I understand, git uses the commit that "master" pointer is on to decide which SVN branch to commit to. That is why the SVN dcommit step fails, since after you completed the merge, and 'mybranch' and 'master' are on the same commit. That commit was originally created from the 'myremotebranch' SVN branch.
Casey
I don't think creating a new merge commit is going to help clarify matters, since the merge info will be lost when it is propagated to the svn repository anyway.
Walter Mundt
@Walter: Yes the merge info will not be committed (you keep it in your git repo, though). But without the new merge commit, there's nothing that can be committed to SVN - dcommit would end up doing nothing (which was the problem of the OP).
Daniel
+2  A: 

In general, you should not use git merge with git svn, because svn, even with branches, doesn't support the kind of merge tracking that git does. When you need to merge a branch, I've had the most success (at least with recent svn) doing a plain svn checkout/merge process and then using git svn rebase to update my git-svn repositories. This preserves svn's native merge tracking metadata, which (AFAIK) git-svn is completely ignorant of.

I'm not totally sure what state your svn repository is in -- I would check to make sure the merge dcommit did what you wanted it to on the trunk. Even if it did, I bet if you look at the contents of the refs/heads/master and refs/remotes/trunk files in your repo, you'll see that they're different at the moment. If that's the case, I would (with no local changes present) do a git-svn fetch followed by a git branch -f master remotes/trunk; git reset --hard master to resync the git branch with the git-svn tracking branch. If you have local changes, you'll have to commit and do something like git rebase master^4 --onto remotes/trunk, where 4 is the number of commits you need to preserve. Alternatively, if they're all uncommitted, stash them with git stash first.

Failing that, you can always get everything into svn and just wipe the repo and get a fresh checkout.

Walter Mundt
I agree with that analysis. +1
VonC