On Thu, Nov 10, 2011 at 12:13 PM, Julian Foad <julian.f...@wandisco.com> wrote: > 2 3 4 5 > BranchA--o----------------------------------------- > \ > \ "A:2" > BranchB-----o---o---------------------------------- > \ > \ "A:2 B:3-4" > BranchC------------o------------------------------- > > Philip and I were prompted by a customer to consider why Subversion copies > mergeinfo from branch to branch, in transitive merges (branch A -> branch B > -> branch C). Why do we need mergeinfo on branch C that refers directly to > A?
Hi Julian, It's not clear from your diagram: is BranchB is a copy of BranchA or a copy of their common parent? If the latter we do need to copy the mergeinfo contained in the diff in merges from BranchB to BranchC, in addition to recording mergeinfo describing that merge. For example: # Start with a vanilla greek tree from our test suite. # Make two branches: >svn copy A branchA A branchA >svn copy A branchB A branchB >svn ci -m "create two branches from 'trunk'" Adding branchA Adding branchB Committed revision 2. # Make a change on our "trunk": >echo trunk edit > A\mu >svn ci -m "trunk edit" Sending A\mu Transmitting file data . Committed revision 3. # Merge that "trunk" change to our first branch: >svn merge ^^/A branchA -c3 --- Merging r3 into 'branchA': U branchA\mu --- Recording mergeinfo for merge of r3 into 'branchA': U branchA >svn pl -vR Properties on 'branchA': svn:mergeinfo /A:3 >svn ci -m "Merge a trunk change from ^/A to ^/branchA" Sending branchA Sending branchA\mu Transmitting file data . Committed revision 4. # Now merge that merge from branchA to branchB: >svn merge ^^/branchA branchB -c4 --- Merging r4 into 'branchB': U branchB\mu U branchB --- Recording mergeinfo for merge of r4 into 'branchB': G branchB >svn st M branchB M branchB\mu # The mergeinfo from the first merge is copied and new mergeinfo # is set to describe *this* merge: >svn diff --depth empty branchB Index: branchB =================================================================== --- branchB (revision 2) +++ branchB (working copy) Property changes on: branchB ___________________________________________________________________ Added: svn:mergeinfo Merged /A:r3 Merged /branchA:r4 # Commit the second merge: >svn ci -m "Merge from ^/branchA to ^/branchB of the prior merge from ^/A to /branchA" Sending branchB Sending branchB\mu Transmitting file data . Committed revision 5. # Make a local change to branchB that would conflict with r3 # if that revision were re-merged: >svn up -q >echo local edit > branchB\mu # Try to remerge r3 from ^/A to branchB, this is a non-conflicting # noop because of the mergeinfo '/A:3' on the target carried from # the merge in r5: >svn merge ^^/A branchB -c3 --- Recording mergeinfo for merge of r3 into 'branchB': U branchB >svn revert -R . Reverted 'branchB\mu' # Now let's manually erase the that mergeinfo with a propset: >svn ps svn:mergeinfo /branchA:4 branchB property 'svn:mergeinfo' set on 'branchB' >svn diff Index: branchB =================================================================== --- branchB (revision 5) +++ branchB (working copy) Property changes on: branchB ___________________________________________________________________ Modified: svn:mergeinfo Reverse-merged /A:r3 >svn pl -vR Properties on 'branchA': svn:mergeinfo /A:3 Properties on 'branchB': svn:mergeinfo /branchA:4 >svn ci -m "Erase transitive mergeinfo" Sending branchB Committed revision 6. # It's probably obvious what the problem is going to be... # ...but if not, now let's try that merge of r3 from ^/A to # branchB again: >svn up -q # Again we make a local change to branchB that would # conflict with r3: >echo local edit > branchB\mu # And BOOM: >svn merge ^^/A branchB -c3 Conflict discovered in 'C:/SVN/src-trunk/Debug/subversion/tests/cmdline/svn-test-work/working_copies/merge_tests-123/branchB/mu'. Select: (p) postpone, (df) diff-full, (e) edit, (mc) mine-conflict, (tc) theirs-conflict, (s) show all options: p --- Merging r3 into 'branchB': C branchB\mu --- Recording mergeinfo for merge of r3 into 'branchB': U branchB Summary of conflicts: Text conflicts: 1 Now if instead you meant that BranchC is a copy of BranchB is a copy of BranchA, then we still have a similar problem. I won't show the whole example, but in the above example we instead copied ^/A to ^/branchA in r2, copied ^/branchA to ^/branchB in r3, made an edit to ^/A/mu in r4, merged r4 from ^/A to ^/branchA in r5, and merged r5 from ^/branchA to /branchB in r6, then we still have a similar problem: >svn ps svn:mergeinfo /branchA:5 branchB property 'svn:mergeinfo' set on 'branchB' >echo local edit > branchB\mu >svn merge ^^/A branchB -c4 Conflict discovered in 'C:/SVN/src-trunk/Debug/subversion/tests/cmdline/svn-test-work/working_copies/merge_tests-124/branchB/mu'. Select: (p) postpone, (df) diff-full, (e) edit, (mc) mine-conflict, (tc) theirs-conflict, (s) show all options: p --- Merging r4 into 'branchB': C branchB\mu --- Recording mergeinfo for merge of r4 into 'branchB': G branchB Summary of conflicts: Text conflicts: 1 Does this answer your question at all (or did I answer a different question ;-) Paul > If, as I believe to be the case, Subversion only supports merge tracking > if the branching graph is tree-shaped, then the only merges allowed to or > from branch C are those to or from branch B (and those to or any further > branches to the "right" of it: D1, D2). And thus the mergeinfo on C that > refers to A is not useful. It's redundant anyway, in the sense that if we > hadn't stored it explicitly then we could crawl the branching graph to find > it, but that's not my concern; rather, I wonder if it is ever actually > providing any benefit. > > It seems to me that we must have done this (propagate mergeinfo) because we > intended that Subversion's merging should support merging patterns more > complex than that. But do we? The big question for me at the moment is: do > people in reality rely on Subversion doing kinds of merging that make use of > this transitive mergeinfo? > > - Julian > >