You are viewing a plain text version of this content. The canonical link for it is here.
Posted to dev@subversion.apache.org by Stefan Sperling <st...@elego.de> on 2017/09/20 08:45:12 UTC

"nearest youngest common ancestor" (was: Re: svn commit: r1808258 - /subversion/trunk/subversion/libsvn_client/conflicts.c)

On Tue, Sep 19, 2017 at 05:59:52PM +0200, Branko Čibej wrote:
> Fixed in r1808258.

Thanks!

> But ... what is a "nearest youngest common ancestor?"

Oh dear... well, it's the YCA of a path component x of path A and
a path component y of path B.

I found no better way to determine a revision to use as a lower bound
during a log search for moves, when given two unrelated paths.

Consider:

  r1: import ^/trunk/foo/bar/alpha
  r2: cp ^/trunk ^/branch
  r3: mv ^/trunk/foo/bar ^/trunk/foo/moo
  r4: mv ^/trunk/foo/moo/alpha ^/trunk/foo/moo/alpha-renamed
  r5: edit ^/trunk/foo/moo/alpha-renamed

  co -r5 ^/branch branch-wc
  merge -c5 ^/trunk branch-wc

You get a 'local missing' tree conflict with:

  ^/trunk/foo/moo/alpha-renamed@4 merge-left
  ^/trunk/foo/moo/alpha-renamed@5 merge-right
  local conflict victim path: branch-wc/foo/moo/alpha-renamed
  
Our preferred solution is to ignore the move and apply the text edit only.
So we want the resolver to correlate the victim to ^/branch/foo/bar/alpha
and apply the edit there.

Take the parent dir of the conflict victim: ^/branch/foo/moo@5
(The implementation should do an existence check here, but currently does not.)
Is there a YCA with ^/trunk/foo/moo/alpha-renamed@5 ? -> No
Is there a YCA with ^/trunk/foo/moo@5 -> No
Is there a YCA with ^/trunk/foo@5 -> No (^/branch/foo/moo@5 does not exist)
Is there a YCA with ^/trunk@5 -> No

Take the parent dir again: ^/branch/foo@5
Is there a YCA with ^/trunk/foo/moo/alpha-renamed@5 ? -> No
Is there a YCA with ^/trunk/foo/moo@5 -> No
Is there a YCA with ^/trunk/foo@5 -> Yes: ^/trunk/foo@r1

The lower bound is r2.
Scan the log for moves between ^/trunk/foo@2 and ^/trunk/foo@5
  r3: mv ^/trunk/foo/bar ^/trunk/foo/moo
  r4: mv ^/trunk/foo/moo/alpha ^/trunk/foo/moo/alpha-renamed

In the conflict description, we can now enlighten the user by showing
relevant moves on ^/trunk's line of history.

Of course, this isn't foolproof. For instance, if someone had copied an
unrelated line of history to ^/trunk/foo, we'd never find a YCA. I expect
that many cases exist where it breaks. But it works in the "common" case
of basic branching/merging of one entire project. And if it doesn't work
we're leaving the user no worse off than before (apart from some time
wasted waiting for the computer).

This is as far as the current implementation has gotten.
The next, still missing, step is to locate the path branch-wc/foo/moo/alpha.
I already have an idea for that, and it's equally hackish.

You may shake your head in disbelief now :)