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

Re: issue-2897(reflective merge solution)

From: Julian Foad <julianfoad_at_btopenworld.com>
Date: Fri, 08 Aug 2008 13:07:54 +0100

Kamesh Jayachandran wrote:
> >> Problem:
> >> - ---------------------
> >> - - Create /feature_branch from /trunk.
> >> - - Synch up change(rX) from /trunk to /feature_branch and commit at rY
> >> along with some other local changes 'Z'.
> >
> > To keep things simple and concrete, I will assume that, before this
> > merge, /feature_branch had already been synchronised with all of the
> > changes up to r(X-1) from /trunk.
>
> Fine. By the above example I meant that 'final reflective merge
> solution' should support cherry picking also.

OK.

 
> > If the user is following best practices, then the extra change 'Z' is
> > what is needed to resolve conflicts.
>
> May be, some times people may do logical conflict resolution(i.e not SVN
> conflict), for example merge may be successful but logically incorrect
> with respect to the state of things in feature branch, user may try to
> fix this inconsistency along with the merge and commit to ensure sanity
> of his commit.

Agreed. Z comprises the changes needed to resolve physical conflicts and
the changes needed to resolve logical conflicts.

 
> >> Available solution:
> >> - ------------------------
> >
> > Solution 0: If you were to use Subversion 1.5's plain "svn
> > merge /feature_branch /trunk" command, then Subversion would omit rY
> > entirely, which is wrong because we need the conflict-resolution part of
> > the change. Without that part, the merge would throw up those same (or
> > similar) conflicts again, which the user would have to resolve again.
>
> I believe you mean 'svn merge trunk_wc ^/feature_branch'

No; the source comes first: 'svn merge ^/feature_branch trunk_wc'. I
expect that's what you meant :-)

> This would *not* leave rY rather it would do a 'mad' merge
> possibly(mostly) causing repeat merge problem.

OK, Mark explained that my assumption there was wrong and the current
merge algorithm attempts to apply rY in this case so as not to throw
away all the "logical conflict" resolution work that may have been
included, even though the "physical conflict" parts will conflict again.

> Only instance it would not cause conflict is when there is enough
> distance between 'trunk' and 'feature_branch' hunks.

I don't understand this. Each hunk from rY that conflicted and was
resolved when rY was created from rX is almost certain to conflict
again, is it not? I don't see how there can be any distance between
where this hunk existed in rX and where it is going to be applied to the
trunk again. It will be applied to the same place where it already
exists.

[...]
> > I know solution 2 can handle many more general cases, but, in the simple
> > cases that "--reintegrate" is intended to handle, does your solution 2
> > achieve the same result, or does it have a different concept of what is
> > the right result?
>
> It has no special cases, it just segregates a range of revisions to
> merge as
> [ordinary_range-1]...[reflective_rev-1]....[reflective-rev-2]...[ordinary_range-N]...
>
> Existing merge call backs are used for 'ordinary_ranges.
>
> Reflective call backs are used for 'reflective revs'.
>
> Purpose of Reflective call backs is 'extract non-reflective change and
> merge the same'.

That doesn't really answer my question. I'm looking for a high-level
end-user's perspective on what the merging process achieves. I think the
answer is that, in the simple cases that "--reintegrate" is intended to
handle, Solution 2 has the same concept of what is the right result
(i.e. that the trunk should end up looking exactly like the
feature_branch does) but does not achieve that result without manual
conflict resolution.

I wonder if it would be possible to make Solution 2 understand how to do
the right thing in this simple case and avoid the need for conflict
resolution. If we could do that, then it would win in every way.

[Snip lots of explanation that's all OK.]

> > So, this works well for non-conflicting changes, and for conflicting
> > changes it produces conflicts by merging the same change again.
> >
> > In summary:
> >
> > * Each source change that originally merged cleanly
> > into /feature_branch will correctly be omitted from the re-integration
> > to /trunk.
> >
> > * Each independent change made to /feature_branch, including changes
> > made in the same revision as a merge, will correctly be re-integrated
> > to /trunk.
> >
> > * Each conflict resolution performed on /feature_branch will correctly
> > be included in the re-integration.
>
> Yes, after annoying with the user with the conflict again as mentioned
> above.

Oh, yes, I suppose so. I was thinking here that changes made by the user
for conflict resolution would not conflict again when merged back, but I
suppose that would be highly unusual.

> > * Each revision from /trunk that conflicted when merged
> > into /feature_branch will wrongly be included in the re-integration,
> > creating new conflicts.
> >
> Yes. May be we can be bit more smart here once we have this stuff working.

I have tried drawing the merge scenario (case 3) on paper. There is a
good way of representing merges, using tokens like "A" to represent a
hunk of text and "Aa" or "A13" to represent a modified version of that
hunk. This diagram shows one file starting in r9 containing three hunks
of text "A", "B", and "C", and developing in trunk and on the branch:

(You need a fixed-width typeface to display this nicely.)

    /trunk /feature_branch
    ____
r9 |A
    |B
    |C

svn copy ^/trunk ^/feature_branch
    ____ ____
r10 |A |A
    |B |B
    |C |C

# Now various modifications are committed...
    ____ ____
r12 |Aa << |A
    |B |B
    |C |Cc <<
    ____ ____
r13 |Aa |A
    |B13 << |B
    |C |Cc
    ____ ____
r17 |Aa |A
    |B13 |B
    |C17 << |Cc
    ____ ____
r20 |A20 << |A
    |B13 |B
    |C17 |Cc
    ____ ____
r29 |A20 |A
    |B29 << |B
    |C17 |Cc

svn merge -c13,17,29 ^/trunk feature_branch_wc
    .... ____
WC .... |A
    .... |B29 << auto-merged
    .... |<C17=C=Cc> << conflict

# Manually resolve.
svn commit
    ____ ____
r40 |A20 |A
    |B29 |B29 << auto-merged
    |C17 |C40 << manually resolved

svn merge ^/feature_branch trunk_wc

# phase 1: a normal merge of r10:39.
# (The only operative change is r12 of /feature_branch.)
    ____
WC |A20
    |B29
    |<C17=C=Cc> << conflict

# Oops: it conflicts already. (Is that what we expected?)
# Manually resolve.
    ____
WC |A20
    |B29
    |C40

# phase 2: a reflective-merge of r40
                ____
( OLDER = |? )
                |?
                |?
                ____
( OLDER + |? )
  c13,17,29 = |?
                |?
                ____
( MINE = |? )
                |?
                |?
    ____
WC |?
    ...

Would you be interested in correcting this and filling in the rest?

- Julian

---------------------------------------------------------------------
To unsubscribe, e-mail: dev-unsubscribe_at_subversion.tigris.org
For additional commands, e-mail: dev-help_at_subversion.tigris.org
Received on 2008-08-08 14:08:20 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.