How do you rebase a git-svn branch and keep the metadata intact?
I recently used git svn branch
to create a branch (in both Subversion and git).
I noticed that (for some reason I'm not sure about; maybe a bug or maybe I created the branch incorrectly?) the git commit for the branch creation has two parents: one at the top of the tree at the time I created the branch (incorrect since I branched from a previous revision) and one at the (expected) previous revision.
This "second parent" causes all kinds of grief for me, since I'm now trying to merge from another branch to the new branch, and git's idea of the common ancestor is incorrect.
I found this question which explains how to force the git branch to have the correct parent by using a rebase. The problem is, the rebase only affected my local branch HEAD, not the remote tied to the git-svn repository. Normal开发者_开发百科ly, this would be a very bad thing, but since I'm the only one using this git-svn repository, I don't care: I just want to move the remote branch to the adjusted commit now.
So my question is: now that I've got the parent for the local branch pointed at the correct commit it branched from, is there a way for me to move the remote branch to the same HEAD, so that I can (for example) run git svn rebase
without it getting confused? (I'm afraid that if I change it by hand, the .git/refs/remotes/<mybranch>/.rev_map...
file won't match up with SVN any more...?)
Edit: To address the question posed in the comment, yes, the branch is checked out. I'm going to change the names of my branches to protect the innocent, but let's imagine it looks like this:
$ git branch
* git_mysvnbranch
git_releasebranch
master
$ git branch -r
trunk
mysvnbranch
releasebranch
Now, when I created the branch, mysvnbranch
had a parent of both trunk, and the arbitrary point off of trunk that I branched from. Now I want to take releasebranch
and merge it into mysvnbranch
, which is when I see a problem. If I launch gitk
it looks like this:
o [git_mysvnbranch] [remotes/mysvnbranch]
|\ <--- bad pointer here
| o [remotes/trunk]
| |
| o
| | o [git_releasebranch] [remotes/releasebranch]
| | |
| o o
| |/
| o
| |
| o
| |
| o
|/
o [arbitrary branch point]
So you can see the problem if I want to merge in [remotes/releasebranch]
. If I do a rebase, I can make it look like this:
o [git_mysvnbranch]
|
| o [remotes/mysvnbranch]
| |\ <--- bad pointer here
| | o [master] [remotes/trunk]
| | |
| | o
| | | o [git_releasebranch] [remotes/releasebranch]
| | | |
| | o o
| | |/
| | o
| | |
| | o
| | |
| | o
| |/
|/
o [arbitrary branch point]
And now I want to git rid of the version of [remotes/mysvnbranch]
with the bad parent, and make it point to where [git_mysvnbranch]
points to instead.
But here's a curious thing that I just found out: the svn metadata might indeed be intact. I just did this:
$ git svn rebase -n
Remote Branch: refs/remotes/mysvnbranch
SVN URL: svn://subversionrepo/branches/mysvnbranch
So maybe I'm worrying about nothing. I will test this a little more to try to find out.
Edit 2: I'm not worrying about nothing. As soon as I tried git svn rebase
from the rebased branch, it tried to re-merge changes that had already been merged into the git branch.
After much pain and suffering, I have found a workaround, but it's not a very good one:
$ svn copy -r <arbitrary-branch-point> svn://subversionrepo/trunk \
svn://subversionrepo/branches/mysvnbranch2
That is, I gave up and recreated the branch with a different name. (using the Subversion client, just to be safe.) Then I did a git svn fetch --all
. I think I'll be able to rebase my work onto the new branch and call it a day. When I check gitk
, the new branch is based on the proper revision.
I hope someone knows of a better workaround, because I don't think this would be acceptable to everyone who has this same problem.
FYI, I think this happened because a branch with the same name was created incorrectly and then deleted, before I started on this. This probably confused git-svn.
精彩评论