On Fri, Dec 09, 2011 at 01:05:02PM +0000, Rob Pointer wrote: > Mark > If you put changes multiple times from trunk to a branch (in development > terms, a re-base) you can cause reflective merges and actually cause more > problems. The recommended merge back into trunk is a reintegrate merge. > I am not sure if this has been addressed in 1.7, but certainly for earlier > versions (anyone please correct me if I am wrong here though :) ). > > The scenario goes > 1) trunk contains file A > 2) copy trunk to branch1 > 3) modify file A in branch1 > 4) add folderb/fileb in trunk > 5) branch (copy) folderb into branch (or merge if it actually works :) ) > 6) do some changes to file A and ffileb > 7) merge back into trunk. > > SVN seems to get confused and when it checks the history of both trunk and > branch1 it doesn't know that the folderb/fileb was added in branch1 using a > copy, therefore it just thinks you added the files on trunk and then > branch1 as two separate operations (for any clearcase users this is an evil > twin scenario). Therefore SVN will create a tree conflict when merging > your branch back into trunk.
Wrong, wrong, wrong. You may believe that Subversion is broken but in fact you're just pushing its buttons the wrong way. To be clear, if you use the correct merge syntax for each step your scenario works just fine. And this applies to 1.6 as well as 1.7. To demonstrate: + rm -rf reflective-merge + mkdir -p reflective-merge + mkdir -p reflective-merge/trunk + echo A + > reflective-merge/trunk/A + svnadmin create /tmp/reflective-merge/repos + svn import reflective-merge/trunk file:////tmp/reflective-merge/repos/trunk -m importing project tree Adding reflective-merge/trunk/A Committed revision 1. + svn copy file:////tmp/reflective-merge/repos/trunk file:////tmp/reflective-merge/repos/branch1 -m creating branch Committed revision 2. + rm -rf reflective-merge/trunk + svn checkout file:////tmp/reflective-merge/repos/trunk reflective-merge/trunk A reflective-merge/trunk/A Checked out revision 2. + svn checkout file:////tmp/reflective-merge/repos/branch1 reflective-merge/branch1 A reflective-merge/branch1/A Checked out revision 2. + echo foo + >> reflective-merge/branch1/A + svn commit -m modify A on branch reflective-merge/branch1 Sending reflective-merge/branch1/A Transmitting file data . Committed revision 3. + svn mkdir reflective-merge/trunk/folderb A reflective-merge/trunk/folderb + echo bar + >> reflective-merge/trunk/folderb/fileb + svn commit -m add folderb/fileb on trunk reflective-merge/trunk Adding reflective-merge/trunk/folderb Committed revision 4. + svn update reflective-merge/branch1 Updating 'reflective-merge/branch1': At revision 4. + svn merge file:////tmp/reflective-merge/repos/trunk reflective-merge/branch1 --accept postpone --- Merging r2 through r4 into 'reflective-merge/branch1': A reflective-merge/branch1/folderb --- Recording mergeinfo for merge of r2 through r4 into 'reflective-merge/branch1': U reflective-merge/branch1 + svn commit reflective-merge/branch1 -m merge trunk into branch (no conflicts) Sending reflective-merge/branch1 Adding reflective-merge/branch1/folderb Committed revision 5. + echo baz + >> reflective-merge/branch1/folderb/fileb + svn commit -m modify folderb/fileb on branch reflective-merge/branch1 + svn update reflective-merge/trunk Updating 'reflective-merge/trunk': At revision 5. + svn merge --reintegrate file:////tmp/reflective-merge/repos/branch1 reflective-merge/trunk --accept postpone --- Merging differences between repository URLs into 'reflective-merge/trunk': U reflective-merge/trunk/A --- Recording mergeinfo for merge between repository URLs into 'reflective-merge/trunk': U reflective-merge/trunk + svn commit reflective-merge/trunk -m reintegrate branch into trunk (no conflicts) Sending reflective-merge/trunk Sending reflective-merge/trunk/A Transmitting file data . Committed revision 6. You only get a tree-conflict if you forget to use --reintegrate in the last merge: + svn update reflective-merge/trunk Updating 'reflective-merge/trunk': At revision 5. + svn merge file:////tmp/reflective-merge/repos/branch1 reflective-merge/trunk --accept postpone --- Merging r2 through r5 into 'reflective-merge/trunk': U reflective-merge/trunk/A C reflective-merge/trunk/folderb --- Recording mergeinfo for merge of r2 through r5 into 'reflective-merge/trunk': U reflective-merge/trunk Summary of conflicts: Tree conflicts: 1 + svn commit reflective-merge/trunk -m reintegrate branch into trunk (no conflicts) subversion/svn/commit-cmd.c:183: (apr_err=155015) subversion/libsvn_client/commit.c:853: (apr_err=155015) subversion/libsvn_client/commit.c:853: (apr_err=155015) svn: E155015: Commit failed (details follow): subversion/libsvn_client/commit_util.c:1154: (apr_err=155015) subversion/libsvn_client/commit_util.c:1154: (apr_err=155015) subversion/libsvn_client/commit_util.c:823: (apr_err=155015) subversion/libsvn_client/commit_util.c:329: (apr_err=155015) svn: E155015: Aborting commit: '/tmp/reflective-merge/trunk/folderb' remains in conflict To understand why you need the --reintegrate, see: http://mail-archives.apache.org/mod_mbox/subversion-dev/201107.mbox/%3c20110720124721.ga7...@ted.stsp.name%3E To understand how to repeatedly merge back and forth between the trunk and the branch, see here: http://svnbook.red-bean.com/en/1.7/svn.branchmerge.advanced.html#svn.branchmerge.advanced.reintegratetwice For some reason understanding the --reintegrate option seems to be a major usability hurdle for many when it comes to understanding merging in Subversion. It would be nice to just make the 'svn merge ^/foobar' magically do whatever people expect. But I don't see a good way of doing that, unfortunately. Once you understand what a 2-URL merge is and how that works, and that any merge is really just a 2-URL merge, it's really not that hard to understand that --reintegrate is just syntactic sugar and when you should use it. > A similar scenario occurs of you copied file A from trunk to branch1 after > modifying it on trunk. SVN will then throw content conflicts, telling you > that you modified the same line in the file in two branches (i.e. trunk > and branch1) and the text is identical. Again not sure if 1.7 fixes this, > but it is definitely present in 1.6.x Again, please verify that you're invoking the tool in the right way before jumping to conclusions. If you don't carefully use the right 'svn merge' invokation syntax for the situation at hand you can easily create conflicts for yourself. See also the output of 'svn help merge' in 1.7, copied here: http://subversion.apache.org/docs/svn-merge.txt