On Thu, Aug 2, 2012 at 10:45 AM, Julian Foad <[email protected]> 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
>