On Thu, Aug 2, 2012 at 10:45 AM, Julian Foad <julianf...@btopenworld.com> wrote:
> Hi Paul.
>
> Thanks for looking at this and the other ('deleted subtrees') thread.  
> Replies in line below...
>
>
> Paul Burba wrote:
>> Julian Foad wrote:
>>>  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
>>
>> What does 's' represent in this diagram?
>
> Something happening to the subtree.
>
>>  In merge_symmetric_tests.py's key 's' represents 'a subtree
>> merge', but that's not the case here, AFAICT.
>
> Yup, sorry for the unclarity.
>
>>>  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?
>>
>> No, but we could easily have had such a merge,
>>
>>                   reintegrate 'everything'
>>                           |
>> A   -----o----o------------x
>>      \    \     \         /
>>       \    \     \       /
>> B      o----x-----s----s---
>>             |     |
>>             |   merge the subtree 'D' only
>>             |
>>           merge 'everything'
>>
>> and still be facing the same problem.
>
>
> I don't think so, because now it is clearly a 'reintegrate' that is needed.  
> I say 'clearly' because now the root path of the merge has mergeinfo on one 
> side, showing that a merge was done in one direction on this *same root path* 
> that we're now wanting to merge.  The rule for using "reintegrate", as far as 
> I am aware, is that you use it when merging in the opposite direction to "the 
> previous merge".  No matter whether "the previous one" means the most recent 
> merge in the tree or the most recent merge of the given root path, in this 
> scenario those are both in the direction A->B, and so both the user and the 
> current symmetric merge code know what to do.  (I should check that it 
> currently does.)

You are quite right, if there was any merge from the root of A to B,
the symmetric merge code path kicks in and alerts us that we aren't
ready for this merge:

>svn pl -vR
Properties on 'A_COPY':
  svn:mergeinfo
    /A:2-3
Properties on 'A_COPY\D':
  svn:mergeinfo
    /A/D:2-7

>svn merge ^^/A_COPY A
..\..\..\subversion\svn\util.c:913: (apr_err=195016)
..\..\..\subversion\svn\merge-cmd.c:163: (apr_err=195016)
..\..\..\subversion\libsvn_client\merge.c:11773: (apr_err=195016)
..\..\..\subversion\libsvn_client\merge.c:11695: (apr_err=195016)
..\..\..\subversion\libsvn_client\merge.c:10743: (apr_err=195016)
svn: E195016: Reintegrate can only be used if revisions 2 through 10
were previously merged from
file:///C:/SVN/src-trunk/Debug/subversion/tests/cmdline/svn-tes
t-work/repositories/merge_automatic_tests-18/A to the reintegrate
source, but this is not the case:
  A_COPY
    Missing ranges: /A:5

> On the other hand, in the test scenario, if "the previous one" means the most 
> recent merge of the given root path (which is what I assumed, but who's to 
> say?), then it's ambiguous because there was no such merge in either 
> 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, with an 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?
>>
>> #1 would be awesome :-) but in the meantime...
>>
>> I take your points about user intent but if the symmetric merge code
>> is meant to do away with the --reintegrate option, I think we should
>> take the more cautious approach and assume the user intends a
>> reintegrate, so IMO (3a) is the best choice.
>
>
> OK, yes.  If I can try to interpret your meaning without saying 
> "reintegrate", it would be: we should take the more cautious approach which 
> is to bail out because of the inconsistent subtree state.  The rule would be, 
> for a request to merge in the direction A->B, roughly speaking:
>
>   * if every node in the tree was last merged A->B or not at all    -> merge 
> in the non-reintegrate style
>
>   * if every node in the tree was last merged B->A, up to the same
>     B revision
>     -> merge in the reintegrate style
>
>
>   * otherwise
>     -> bail out and report the subtree inconsistency
>
> I'll try to formulate that rule more precisely.

Did you ever look into this any further?

I'm going over the XFailing tests to determine what is considered a
1.8 blocker and merge_automatic_tests.py 18: 'reintegrate considers
source subtree mergeinfo' is obviously still set to XFail.

-- 
Paul T. Burba
CollabNet, Inc. -- www.collab.net -- Enterprise Cloud Development
Skype: ptburba

> In particular, that rough statement doesn't address the difference between 
> 'complete' merges (which don't leave unmerged gaps before any merged revs) 
> and 'cherry-pick' merges (which do).
>
> - Julian
>

Reply via email to