[svn.haxx.se] · SVN Dev · SVN Users · SVN Org · TSVN Dev · TSVN Users · Subclipse Dev · Subclipse Users · this month's index

Symmetric merge and subtrees

From: Julian Foad <julianfoad_at_btopenworld.com>
Date: Tue, 17 Jul 2012 18:28:25 +0100 (BST)

There are some merge scenarios for which it's not clear whether the user should specify '--reintegrate' or not.  We need to decide what the 'symmetric' (i.e. automatically-choosing) code should do in those cases.

The following example is adapted from merge_symmetric_tests.py 18, subtree_to_and_fro(), "reintegrate considers source subtree mergeinfo":

                   reintegrate 'everything'
                           |
  A ------o-s--------------x
      \          \        /
       \          \      /
  B     o-----s----s----s---
                   |
                 merge the subtree 'D' only

In terms of commands (assume a commit after each step):

  svn cp A B
  edit A
  edit A/D
  edit B/D  svn merge ^/A/D B/D
  edit B/D
  svn merge --reintegrate ^/B A

The output from "merge --reintegrate" is:

  svn: E195016: Reintegrate can only be used if
  revisions 2 through 8 were previously merged [...]

But why did the user choose a 'reintegrate' merge in this example, when there has been no merge of the branch root in the A->B direction?  Or, from another angle, what if we have this similar scenario?

                   merge 'everything'
                           |
  A     o-o-s--------------x
       /         \        /
      /           \      /
  B ----------s----s----s---

Given this example, it looks like a non-reintegrate merge might be the user's choice for the final merge (and for the intermediate merge... either a reintegrate or non-reintegrate); but all that's changed in this example is which branch was branched from which, and that shouldn't make any difference.  AFAIK we don't document a rule for whether '--reintegrate' should be used; it's ambiguous.

We have three possible results when we request a merge:

  (1) a correct merge
  (2) a wrong merge, with spurious conflicts
  (3) bail out

Currently, 'merge' gives (2), 'merge --reintegrate' gives (3), and 'merge --symmetric' gives (2).

The subtree_to_and_fro() test expects 'merge --symmetric' to give result (3), but the symmetric merge currently sees that case as one in which a *non-reintegrate* merge is needed, and goes ahead to produce a merged result (with a conflict):

  --- Merging r2 through r8 into 'A':
  U    A/D/gamma
  C    A/D/H/psi
  [...]

Is the symmetric merge 'broken'?  This test claims so, on the basis of expecting it to behave like a reintegrate merge.  However, we can't be strictly backward-compatible with both the reintegrate and the non-reintegrate behaviours if we have to pick one, because they differ.  What do we want to see here?

I think it depends what the user is thinking.  If the user is thinking "just help me merge everything that needs to be merged", then the user probably would have used the plain 'merge' command in 1.7, and would prefer a wrong merge with spurious conflicts, given that we haven't yet implemented a correct merge.  If the user is thinking "this is a reintegration, and I believe my branch was sync'd with the trunk recently", then the user probably would prefer this merge to bail out like 'reintegrate' does.

It almost goes without saying that if and when we have implemented a correct merge then that is the right thing to do, and that will resolve the ambiguity.  (When we do that, there is still the possibility of giving the user an option to make Subversion detect and report whether the required merge has anything complex about it -- subtrees, cherry-picked revisions, and so on -- because the user might want the mental security of confirming that in fact the merge is as simple as the user expects it to be.  But that is another topic.)

Our options for what 'symmetric' merge will do, in cases like this [1], are:

  (1) Implement correct merging.
  (2) Merge wrongly, with spurious conflicts, like plain 1.7 'merge'.
  (2a) (2) by default, withan option to check and bail out like (3).
  (3) Bail out like 1.7 'reintegrate'.
  (3a) (3) by default, with an option to force the merge to proceed like (2).

If we choose (2), then we break strict compatibility with 1.7 'reintegrate' merge.  If we choose (3), then we break strict compatibility with 1.7 'non-reintegrate' merge.

I'd like to do (1), but, in the meantime, would we be happy with one of the alternatives?

- Julian

[1] At the moment, 'cases like this' means cases where the specified merge root node was last merged in the same direction as the current merge, or was never merged before.  That is, the symmetric merge code chooses whether to do a reintegrate style of merge or a non-reintegrate style of merge based on the direction of this merge relative to the direction of the last merge of the specified root node, not based on any merges that may have been done to subtrees.  That does NOT mean it doesn't handle subtrees; it handles them just the same as
1.7 (reintegrate or plain) merge does.  It just means subtrees don't affect the decision of which style of merge it uses.

--
Certified & Supported Apache Subversion Downloads: http://www.wandisco.com/subversion/download
Received on 2012-07-17 19:28:59 CEST

This is an archived mail posted to the Subversion Dev mailing list.

This site is subject to the Apache Privacy Policy and the Apache Public Forum Archive Policy.