On Mon, Jan 14, 2013 at 8:49 AM, David Moon <david.m...@versata.com> wrote: > Subversion creates an unnecessary tree conflict when two branches of a > directory are merged. See the transcript below. Since the contents of the > directory do not conflict between the two branches, it should just add both > subdirectories to the directory and not report any conflict. In my opinion, > that should be the default merge behavior, but there isn't even any way > using svn resolve to tell it to do that! The only thing svn resolve can do > is lose the incoming change. > > The unnecessary tree conflict does not always happen, based on I know not > what. But the transcript below seems to be a reliable way to reproduce it. > > This transcript is boiled down to a simple test case. In the real thing > there were too many of these tree conflicts to fix by hand, so fixing it by > hand is not a solution even if I could figure out how to fix it by hand. > > $REPOS is file:/// something. > >> svn --version > svn, version 1.7.8 (r1419691) > compiled Dec 12 2012, 14:18:28 > >> svn mkdir --parents $REPOS/test1/branches/B1/D1/D2/A -m xx > >> svn mkdir --parents $REPOS/test1/tags/T1/D1/D2/B -m xx > >> svn co $REPOS/test1/branches/B1/D1/D2/A >> echo test > A/test1.txt >> cd A; svn add test1.txt >> svn commit -m xx >> cd .. > >> svn co $REPOS/test1/tags/T1/D1/D2/B >> echo test > B/test2.txt >> cd B; svn add test2.txt >> svn commit -m xx >> cd .. > >> svn copy $REPOS/test1/tags/T1 $REPOS/test1/branches/B2 -m xx > >> svn list -R $REPOS/test1/branches/B1 > D1/ > D1/D2/ > D1/D2/A/ > D1/D2/A/test1.txt >> svn list -R $REPOS/test1/branches/B2 > D1/ > D1/D2/ > D1/D2/B/ > D1/D2/B/test2.txt > >> svn co $REPOS/test1/branches/B2 >> cd B2 >> svn merge $REPOS/test1/branches/B1 > --- Merging r167502 through r167505 into '.': > C D1/D2/A > --- Recording mergeinfo for merge of r167502 through r167505 into '.': > U . > Summary of conflicts: > Tree conflicts: 1 >> svn status > M . > ! C D1/D2/A > > local delete, incoming edit upon merge > Summary of conflicts: > Tree conflicts: 1 >> ls D1/D2 > B/ > > Note: ls D1/D2 should say A/ B/ and there should be no tree conflict. > > In the real thing, the svn status explanation of the tree conflict is > usually "local add, incoming add upon merge." I can't explain why the > simple test case says local delete instead. I don't know if this matters. > > I can't say that Subversion is not behaving according to the documentation, > because the documentation at http://svnbook.red-bean.com/en/1.7/index.html > is extremely vague about this aspect of Subversion. But it's not behaving > in a useful way. > > I hope this bug report is useful to you. I can't wait for a fix, so I am > changing to a different strategy that does not depend on Subversion merge.
Looks to me like you're using the merge command wrong. 1) You're using the sync merge format of the 1.7.x merge command, however the two branches you're merging (B1 and B2) have no common ancestor. Since B2 was copied from T1 which you independently created, there's really no way for the command to know what to do. The fact that it does anything can be considered a bug, I'll note that on trunk right now the example you give above fails with the following error: [[[ svn: E205000: Try 'svn help merge' for more information svn: E205000: Source and target must be different but related branches svn: E205000: Source and target have no common ancestor: 'file:///Users/breser/moon/repo/test1/branches/B1@head' and '.@unspecified' ]]] Based on the behavior it seems that in 1.7.x the command is somehow trying to do a cherry-pick. 2) If what you're really intending to do here is a cherry-pick merge of the changes that were made on B1 (adding A and test1.txt) then you want to use the cherry-pick form: svn merge [-c M[,N...] | -r N:M ...] SOURCE[@REV] [TARGET_WCPATH] Note that you need either -c or -r to specify the range of revisions. You might be tempted to try (assuming that r1 is where A was added) svn merge -r0:HEAD $REPOS/test1/branches/B1 However, you'll still get the conflict: [[[ $ svn merge -r0:HEAD $REPOS/test1/branches/B1 --- Merging r2 through r5 into '.': C D1/D2/A --- Recording mergeinfo for merge of r2 through r5 into '.': U . Summary of conflicts: Tree conflicts: 1 ]]] and a similar status: [[[ $ svn status M . ! C D1/D2/A > local delete, incoming edit upon merge Summary of conflicts: Tree conflicts: 1 ]]] If I modify your example by adding the following two commands onto the front: [[[ svn mkdir --parents $REPOS/test1/branches/B1/D1/D2 -m xx svn mkdir --parents $REPOS/test1/tags/T1/D1/D2 -m xx ]]] Which shifts the creation of your shared paths from the differences onto separate versions (and as such A isn't created until r3) then I get the following a successful merge by doing: [[[ $ svn merge -r2:HEAD $REPOS/test1/branches/B1 --- Merging r3 through r7 into '.': A D1/D2/A A D1/D2/A/test1.txt --- Recording mergeinfo for merge of r3 through r7 into '.': U . $ svn status M . A + D1/D2/A ]]] So what's happening here is that Subversion is conflicting on trying to create D1 and D2 because the creation of these directories are in the revision you're trying to merge. You can work around this by doing: svn mkdir D1/D2/A and then doing the merge as follows: svn merge -r0:HEAD $REPOS/test1/branches/B1/D1/D2/A D1/D2/A This works because the creation of those directories is now filtered out as happening below the path you're merging. It's hard to say if there's a bug here or not based on what you've said so far. Your example use case seems so far from any realistic scenario that it's hard to envision what you're actually doing here. The local delete on the status notification is a bug of some sort in 1.7 but it doesn't happen in trunk and so many things have changed between the two it's really hard to be sure why. I can understand the argument that maybe we should handle this directory creation conflict a little more gracefully, but it does seem to be a legitimate tree conflict. Hopefully someone else can chime in with a little more knowledge of this code than I have.