I may have found a Subversion bug, and I would like to make sure it is so before I report it.
Consider the following sequence of actions:
Create a new SVN repository with /trunk and /branches in it:
~$ svnadmin create testrepo
~$ svn co file:///home/user/testrepo testwd
Checked out revision 0.
~$ cd testwd/
testwd$ svn mkdir trunk branches
A trunk
A branches
testwd$ svn commit
Adding branches
Adding trunk
Committed revision 1.
testwd$ cd ..
Check out a working directory of the trunk:
~$ svn co file:///home/user/testrepo/trunk testtrunkwd
Checked out revision 1.
~$ cd testtrunkwd/
Create a new symbolic link and commit it (assuming /home/user/test
exists):
testtrunkwd$ ln -s /home/user/test x
testtrunkwd$ svn add x
A x
testtrunkwd$ svn commit
Adding x
Transmitting file data .
Committed revision 2.
Create a branch called mybranch
:
testtrunkwd$ svn copy ^/trunk ^/branches/mybranch
Committed revision 3.
Delete this new link, commit, update, create a directory with the same name, commit:
testtrunkwd$ svn rm x
D x
testtrunkwd$ svn commit
Deleting x
Committed revision 4.
testtrunkwd$ svn update
At revision 4.
testtrunkwd$ svn mkdir x
A x
testtrunkwd$ svn commit
Adding x
Committed revision 5.
testtrunkwd$ cd ..
Check out a working directory of the branch:
~$ svn co file:///home/user/testrepo/branches/mybranch testbranchwd
A testbranchwd/x
Checked out revision 5.
~$ cd testbranchwd/
Merge the changes from the trunk in to the branch:
testbranchwd$ svn merge ^/trunk
svn: Can't replace 'x' with a node of a differing type; the deletion must be committed and the parent updated before adding 'x'
My question is whether I did anything wrong, or this is indeed a Subversion bug.
The (bad) solution I found for this problem is to do a two-part merge:
Create a new working copy of the branch:
testbranchwd$ cd ..
~$ svn co file:///home/user/testrepo/branches/mybranch testbranchwd2
A testbranchwd2/x
Checked out revision 5.
~$ cd testbranchwd2
Merge the changes from the trunk up to the point where the link x
was removed:
testbranchwd2$ svn merge -r3:4 ^/trunk
--- Merging r4 into '.':
D x
Commit the merge and update the working copy of the branch (without any of these steps, I get the error message from above again when trying to merge):
testbranchwd2$ svn commit
Sending .
Deleting x
Committed revision 6.
testbranchwd2$ svn update
At revision 6.
testbranchwd2$ svn merge ^/trunk
--- Merging r5 through r6 into '.':
A x
And this merge works successfully.
Although this solution works, it has several disadvantages:
- It took me about two days to come up with this: the error message is misleading and it's not at all clear what should be done.
- It will have to be done for each and every branch that was created (or last merged into from trunk) before the link was removed, which is a lot of hassle if there are many of them.
- It doesn't seem like the right behavior for
merge
. Why should a branch care if a link was replaced by a directory in the trunk? The branch just wants all the changes to be merged into it, which means the result should be identical to the trunk when no change has been done in the branch to the relevant files. If this solution is attempted in the first working directory of the branch (after the faulty merge), it doesn't work.
svn revert
doesn't help, because this partial merge leaves the working copy in some inconsistent state:
Ifsvn status
is done in the first working copy of the branch, this is the result:testbranchwd$ svn status
~ x
And this~
meansversioned item obstructed by some item of a different kind
(according tosvn help status
), which I don't know how to fix (the merge should have overcome this). So the only way (I think) is to checkout a new working copy for the branch.
So, is there a better solution than what I did? Should I file a bug?
Thanks, Daniel