tags:

views:

3040

answers:

5

Last week, I made a number of changes to my local branch before leaving town for the weekend. This morning I wanted to dcommit all of those changes to the company's Svn repository, but I get a merge conflict in one file:

Merge conflict during commit: Your file or directory 'build.properties.sample' is probably out-of-date: The version resource does not correspond to the resource within the transaction. Either the requested version resource is out of date (needs to be updated), or the requested version resource is newer than the transaction root (restart the commit).

I'm not sure exactly why I'm getting this, but before attempting to dcommit, I did a git svn rebase. That "overwrote" my commits. To recover from that, I did a git reset --hard HEAD@{1}. Now my working copy seems to be where I expect it to be, but I have no idea how to get past the merge conflict; there's not actually any conflict to resolve that I can find.

Any thoughts would be appreciated.

EDIT: Just wanted to specify that I am working locally. I have a local branch for the trunk that references svn/trunk (the remote branch). All of my work was done on the local trunk:

$ git branch
  maint-1.0.x
  master
  * trunk
$ git branch -r
  svn/maintenance/my-project-1.0.0
  svn/trunk

Similarly, git log currently shows 10 commits on my local trunk since the last commit with a Svn ID.

Hopefully that answers a few questions.

Thanks again.

+12  A: 

You should have created a local branch, and done the work on that, then when you get back, you update the master, rebase to the local branch, merge back to master then dcommit.

So I'd try copying out the changes, to back them up.

Create a local branch from the has svn sync point, merge your changes in there. Then back out the changes in the master branch, fetch, rebase to the branch, merge in from the local branch, fix any conflicts, then dcommit.

$ git checkout -b backup    # create a local backup branch with all your work
$ git checkout master   
$ git checkout -b backup2   # 2nd copy just to be safe
$ git checkout master
$ git reset --hard <this is the revision of the last svn-id> # clean up master to make the svn merge easier
$ git svn fetch    # this should update to the current version on the svn server
$ git rebase master backup  # may get a conflict here, fix and commit
... # after conflict is fixed and commited
$ git checkout master 
$ git merge backup --ff  # merge in your local commits
$ git svn dcommit        # push back to the svn

You can get additional info here

Another answer you might be interested in.

git-svn workflow articles

Simple

Another

sfossen
New git user, so slow down. :-) I have a local branch, trunk, checked out from a remote branch, svn/trunk. The work is on my local trunk branch. There are about 12 commits, many with shared files. I need to retain the commit history rather than rebuild it if at all possible.
Rob Wilkerson
run git branch, if you only have "master", you don't have a local branch :P
sfossen
do a git log to find the last point that is tagged with an svn id.
sfossen
I have:> $ git branch maint-1.0.x master* trunkThe **git log** command shows 10 local commits of mine since the last Svn commit by another team member.
Rob Wilkerson
(sorry about the formatting in last comment. I assumed markdown could be used in comments as well)
Rob Wilkerson
I did try the steps you've outlined here (replacing "master" with trunk") and it didn't work. I still get exactly the same error. Thanks for your help with this.
Rob Wilkerson
+2  A: 

To complete sfossen's excellent answer, here is some details:

With git-svn, you get by default a local branch named master. You should not do any work on it, only keep it up-to-date with the svn trunk branch with:

  • git svn fetch to get the history from the svn trunk branch on your local trunk branch: it will not apply those modifications on your working directory
  • git checkout master to switch on trunk branch (only if you were on another branch)
  • git rebase trunk to synchronize master with trunk.

However, all your modifications should be done on another local branch (lets call it local-devel).

  • git branch local-devel
  • git checkout local-devel

If you have an urgent fix to do:

  • git checkout master : swith on master(),
  • git svn fetch && git rebase trunk to update it with svn trunk
  • git branch fastfix && git checkout fastfix, branch it
  • fix the bug, compile, test,
  • git commit -a: local commit,
  • git svn dcommit update the modification to the distant svn repo
  • git checkout master && git rebase trunk: update master again
  • git branch -D fastfix: remove hotfix branch
  • git checkout local-devel && git rebase master: get back to dev, with the updated history done on master replayed on your dev branch

It is a bit of an hassle at first, but way more comfortable than an svn diff in a file to be applied later.

VonC
I've edited the post to indicate accordingly, but I am working on a local branch. I still can't dcommit my local commits, though. The file git's complaining about is one that I modified in a local commit. How can I tell it to keep mine or at least see the diffs?
Rob Wilkerson
Yes the issue comes from your work on your local trunk branch, instead of dedicated one. local/trunk should only be used for synchronization with the distant svn trunk.
VonC
May be a 'git svn rebase" (on your local trunk) first may allow you then to "git svn dcommit' after ?
VonC
Hmmm. I guess I don't understand. Are you saying that I should be working directly on my git repository's svn/trunk directly? As in "git co svn/trunk"?
Rob Wilkerson
What I mean is: it look like trunk (on which you have worked) and svn/trunk are out of sync, hence my suggestion to make a "git svn rebase" on your trunk (not svn/trunk), before making any "git svn dcommit" from any branch. First synchronize local and remote trunk, then dcommit
VonC
With apologies for my own density on this...isn't that what I did originally? That was the first thing I did before trying to dcommit. I was on my local trunk and did a git svn rebase which overwrote my commits so I used the reflog to get back a point where my commits were in place.
Rob Wilkerson
I did the rebase because I'm so used to doing an svn update before my commits. :-)
Rob Wilkerson
Some further investigation b/t meetings shows me that what happened is a local commit was pushed, but not recorded in git. It's in my svn log, but has no svn id in Git. There are 9 more local commits after it. Is there a way to delete that one? That should allow the dcommit to go through, I think.
Rob Wilkerson
Could you complete your question with the precise output of "git log --pretty=oneline" and your relevant svn log ?
VonC
+6  A: 

With much appreciation for VonC and sfassen's extraordinary patience with me, the solution sort of worked itself out. I don't know how or why, but maybe my initial rebase didn't work. To fix it I ended up rebasing again. From my local trunk branch:

$ git co -b backup  # backup the commits to my local trunk
$ git co trunk      # return to the local trunk
$ git svn rebase    # rebase the trunk from the Svn server
$ git br -d backup  # delete the backup branch

The key, of course, was that the rebase worked this time. I have no idea why it didn't work when I first did it, but I can't roll the clock back so I won't dwell on it.

Thanks again for everyone's suggestions and patience with a newbie.

Rob Wilkerson
Yes! Glad you solved it! However, I would keep local trunk as a local mirror of svn/trunk, without making any modification on it: since branching and (above all) merging is cheap in Git... working on "master" or a local dev branch as described in my answer might be "easier" when it comes to dcommit
VonC
By the way, +1 for your update on this issue ;)
VonC
Glad it worked out. You will need to accept one of the answers to remove this from the unanswered questions though.
sfossen
@sfossen: Will do.@VonC: I'm not sure I understand that path at all. It sounds like I've got one remote and two local branches and that just doesn't make sense to me for some reason. Cheap or not, it just feels like branching overkill to me. Can you get remedial to outline the reasoning?
Rob Wilkerson
@Rob Wilkerson: Reason to keep the local trunk as a mirror of svn/trunk, is so you have a stable/easy to update/branch from point. Having a second local development branch of the trunk, allows easier merging and a backup.
sfossen
... Also if you need to branch, for a special feature, you already have a proper point. I'll add some articles to my answer.
sfossen
@Rob: As I explain in http://stackoverflow.com/questions/16142#114384, a branch is for a given "development effort". Here trunk represent the "effort" to reflect remote trunk. If that becomes incompatibles with current dev (because of tricky dcommit), another branch is needed. As simple as that.
VonC
+1  A: 

I was going to comment, but thought this deserved more visibility...

git svn rebase is supposed to re-write your commits. From the description and comments, I get the impression that after you rebased, you forced your old commits back on top. The commits have to be replaced with newer versions that don't conflict.

To avoid having to dig through the reflog, you might want to get in the habit of making a quick tag before doing your git svn dcommit. After the dcommit succeeds, delete the tag. If the tag fails, you can do a git reset --hard followed by a git merge <tag>. Re-run your rebase to get your history back in order, re-tag and re-dcommit again.

Ryan Graham
Yeah, I'm still working through my svn mindset, so I keep doing the Git version of svn update before I dcommit. The fact that it overwrote my commits didn't surprise me once I realized what I'd done. Once it was done, though, I had to fight my way back to where I was before the rebase.
Rob Wilkerson
You shouldn't be fighting anything after a rebase. If you are, something is wrong. All of your local commits that haven't been pushed to svn should still be there. If you're getting collisions during rebase, that's a whole other problem.
Ryan Graham
If you haven't already, try using one of the GUI front-ends to visualize the branching. I prefer 'gitk --all' myself.
Ryan Graham
+1  A: 

I had a similar situation. I was doing an git svn dcommit over a bad network connection and it failed at some point. I've discovered that the problem was caused by the fact that Subversion repository already had a new commit, but local git-svn counterpart considered that a commit was not in SVN yet. Solutions from other answers here did not help, however this did:

git svn reset -r <last_svn_commit_git_was_aware_of>
git svn fetch
git svn rebase

After this I was finally able to do git svn dcommit without any errors.

abbot