tags:

views:

67

answers:

1

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:
    If svn status is done in the first working copy of the branch, this is the result:

    testbranchwd$ svn status
    ~ x
    And this ~ means versioned item obstructed by some item of a different kind (according to svn 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

A: 

Well, apparently I should have deleted x, committed the delete to the branch, updated and then run the merge as normal.

I've been told there will be a complete rewrite of the working copy handling code in Subversion 1.7.

Daniel Hershcovich