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

Re: 2-URL merges incorrectly reverse-merge mergeinfo for merge target?

From: C. Michael Pilato <cmpilato_at_collab.net>
Date: Wed, 19 May 2010 10:11:57 -0400

Stefan Sperling wrote:
> You said the algorithm was:
> the reverse-merge of the diff between "ancestor" and "left"
> + the merge of the diff between "ancestor" and "right"
> Unless I'm mistaken, in this case ancestor is trunk_at_6,
> left is trunk_at_15, and right is feature1_at_15.

trunk_at_5 is actually the ancestor, since it was the copy source for

> The mergeinfo diffs are as follows (omitting other changes svn diff prints):
> $ svn diff ^/trunk_at_15 ^/trunk_at_6
> Property changes on: .
> ___________________________________________________________________
> Modified: svn:mergeinfo
> Reverse-merged /branches/feature2:r10-11

Oops! You've overlooked (or I've failed to correctly describe) a key part
of this algorithm. Yes, the mergeinfo diff between trunk_at_15 and trunk_at_5 is
{ -branches/feature2:10-11 } (note the minus sign at the head of that). But
there's also the natural history of that leg of the merge to be considered.
 So the full bit of mergeinfo changes applied per that leg of the 2-URL
merge is { -branches/feature2:10-11, -trunk:6-15 }.

> $ svn diff ^/trunk_at_15 ^/branches/feature1_at_15
> Property changes on: .
> ___________________________________________________________________
> Modified: svn:mergeinfo
> Merged /trunk:r6-14
> The second mergeinfo diff looks correct, and is a superset of the
> current trunk mergeinfo on feature2 (/trunk:10-13).

Well, here again, it's really { +trunk:6-14, +branches/feature1:6-15 }.

Today we do the real merge (directly between "left" and "right", applied to
the target). Then we do a pair of --record-only merges for the mergeinfo
bit: b/w "ancestor" and "right" applied to target (this tends to be
additive), then b/w "left" and "ancestor" applied to targe (which is
subtractive). And we do things in that order.

So what is probably happening here is that your superset of trunk mergeinfo
additions is being applied first, swallowing the original trunk:10-13 and
making it trunk:6-14, then in that second --record-only step the nasty
-trunk:6-15 is being applied, leaving a net diff of the removal of the
original trunk:10-13 mergeinfo. The -branches/feature2 portion goes nowhere
(because we can't record negative mergeinfo). And the branches/feature1
stuff remains.

Note that if we change the order of operations a bit -- if we calculate the
merge-driven mergeinfo diff first, and then apply it to the target, we're in
better shape:

   {trunk:6-14, feature1:6-15} - {feature2:10-11 -trunk:6-15} =
        {-trunk:15, feature1:6-15, -feature2:10-11}

   {-trunk:15, feature1:6-15, -feature2:10-11} + {trunk:10-13} =
        {trunk:10-13, -trunk:15, feature1:6-15, -feature2:10-11}

   With all the unrecordable negative mergeinfo removed, that's
        {trunk:10-13, feature1:6-15}

Making the final mergeinfo diff for the operation simply:

    Merged /branches/feature1:6-15

Does that make sense?

C. Michael Pilato <cmpilato_at_collab.net>
CollabNet   <>   www.collab.net   <>   Distributed Development On Demand

Received on 2010-05-19 16:12:42 CEST

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