git@vger.kernel.org mailing list mirror (one of many)
 help / color / mirror / code / Atom feed
From: Michael Haggerty <mhagger@alum.mit.edu>
To: Junio C Hamano <gitster@pobox.com>
Cc: git discussion list <git@vger.kernel.org>,
	Kevin Bracey <kevin@bracey.fi>
Subject: Re: Bug when git rev-list options "--first-parent" and "--ancestry-path" are used together?
Date: Sat, 25 May 2013 21:54:30 +0200	[thread overview]
Message-ID: <51A116F6.7080907@alum.mit.edu> (raw)
In-Reply-To: <7v4nds9rhh.fsf@alter.siamese.dyndns.org>

On 05/24/2013 08:12 PM, Junio C Hamano wrote:
> Michael Haggerty <mhagger@alum.mit.edu> writes:
> 
>> Now assume a slightly more complicated situation, in which master has
>> been merged to feature branch at some point:
>>
>> o - 0 - 1 - 2 - 3 - 4    ← master
>>      \       \
>>       A - B - C - D      ← branch
>>            \     /
>>             X - Y
>>
>> Now when we do an incremental merge branch into master, how do we
>> generate the list of commits to put one each axis of the table?  The
>> merge base is "2", so I think the best answer is
>>
>> 1- 2 - 3  - 4   ← master
>>    |   |    |
>>    C - C3 - C4
>>    |   |    |
>>    D - D3 - D4  ← final merge
>>    ↑
>>  branch
> 
> I am not sure if that is the best answer, though.
> 
> After managing to create Cn, if a change between C and D (which come
> from X and Y) is too complex, wouldn't you want to break down the
> task to come up with Dn recursively into a smaller subtask of
> merging X first and then Y on top and finally D?

OK, so let's assume that C3 is done and D3 is giving us problems:

o - 0 - 1 - 2 - 3 - 4    ← master
     \       \   \
      \       \   C3- ?
       \       \ /   /
        A - B - C - D      ← branch
             \     /
              X - Y

Your proposal is not to merge D directly but rather to merge X then Y.

o - 0 - 1 - 2 - 3 - 4    ← master
     \       \   \
      \       \   C3 --- X3 - Y3 - D3
       \       \ /      /    /    /
        A - B - C - D- / -- / ---'   ← the lines here...
             \     /  /    /
              X - Y- / ---'          ← ...and here don't intersect
               \    /
                `--'

The problem is that the merges that would be required are not able to
take advantage of the conflict resolution that was done in D:

The merge base for X3 would be B.  This is a little bit wrong because X3
includes C among its ancestors, so creating X3 requires some of the
conflicts between X and C (which were resolved once in D) to be resolved
again.

The merge base for Y3 would be X.  Note that Y3 already includes C and Y
among its ancestors.  Therefore, resolving Y3 involves resolving the
same conflicts between Y and C that were already resolved in D.  But
since merge Y3 doesn't know about D, the user would be forced to resolve
those conflicts again (albeit maybe helped by something like rerere).

And merge D3 would have two merge bases, C and Y.  This is related to
the fact that there are now two independent known resolutions for
merging C and Y, namely D and Y3.

Given that Y3 in the above scenario needs to include include C (via C3)
and also Y, it seems to me that this merge is superfluous.  It should
have exactly the same content as D3, assuming that the conflicts are
resolved the same way.  Therefore one could skip Y3 and proceed directly
to D3:

o - 0 - 1 - 2 - 3 - 4    ← master
     \       \   \
      \       \   C3 --- X3 - D3
       \       \ /      /    /
        A - B - C - D- / ---'        ← the lines here...
             \     /  /
              X - Y  /               ← ...and here don't intersect
               \    /
                `--'

This merge could take advantage of the conflict resolution that was done
in D.  It would have an unambiguous merge base, C.

But I still think that this approach is not as clean as an incremental
merge of two linear branches, because X3 requires some of the same
conflicts to be resolved as were already resolved in D.

Incidentally, if merge D had been done incrementally and the full
incremental merge resolution had been kept, then we would have the
missing merge CX that would allow us to compute D3 incrementally:

o - 0 - 1 - 2 - 3 - 4    ← master
    |       |   |
    A - B - C - C3
        |   |   |
        X - CX- C3X
        |   |   |
        Y - D - D3

I think that all of the required merges have sane merge-bases and take
advantage of all of the merges that have been done previously.  This is
another case where an incremental merges contains information that can
be useful for the future.

>> The simplest way I can think of to generate the list C,D is
>>
>>     git rev-list --first-parent --ancestry-path 2..D
>>
>> We need --ancestry-path to avoid getting commits A and B.  It's still
>> not clear that this is always the best approach but at least it seems
>> safe.
> 
> Hmm, while I agree that A and B will be omitted by using ancestry
> path on the example topology, I need to be convinced that it is
> impossible to end up with disjoint segments of a history in any
> ancestry graph by combining -f-p and -a-p that way to feel "safe".

If by "disjoint" you mean that the history contains gaps, that is
exactly what happens in the case I described in my last email:

o - 0 - 1 - 2 - 3 - 4    ← master
     \       \
      A - B - C --.
           \       \
            X - Y - D    ← branch

The result of "git rev-list --first-parent --ancestry-path 2..D" would
be only D and commit C would disappear into the "gap".

I am willing to accept that for my application, because the incremental
merge algorithm can work despite gaps in the history but it cannot work
if the ancestry property is not met.

>> This is my reason for wanting --first-parent and --ancestry-path to work
>> together.
>>
>> For now I'm just running rev-list twice and computing the intersection
>> by hand, but it was surprising that git could not do this for me.
> 
> Wouldn't you be able to read everything you need out of a single
> 
> 	git rev-list --left-right --parents master...branch
> 
> output?
> 
> By the way, there is a fairly major fixes to the revision traversal
> machinery that has been parked on pu, which leads to 141efdba57b1
> (revision.c: make default history consider bottom commits,
> 2013-05-16).  The topic revises the semantics of ancestry-path to
> bring more sanity to it.
> 
> I haven't had time to see how it changes the situation for the use
> case you described in the message I am responding to, but I think it
> is worth checking to see how well it meshes with your expectation,
> and if it doesn't involve Kevin in the design discussion.

I'll look into all of these suggestions; thanks.  I'm also CCing Kevin
on this email.

Michael

-- 
Michael Haggerty
mhagger@alum.mit.edu
http://softwareswirl.blogspot.com/

      parent reply	other threads:[~2013-05-25 19:54 UTC|newest]

Thread overview: 4+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2013-05-23 10:07 Bug when git rev-list options "--first-parent" and "--ancestry-path" are used together? Michael Haggerty
2013-05-23 17:20 ` Junio C Hamano
2013-05-25 18:40   ` Michael Haggerty
     [not found]   ` <519F0B2F.3090701@alum.mit.edu>
     [not found]     ` <7v4nds9rhh.fsf@alter.siamese.dyndns.org>
2013-05-25 19:54       ` Michael Haggerty [this message]

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

  List information: http://vger.kernel.org/majordomo-info.html

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=51A116F6.7080907@alum.mit.edu \
    --to=mhagger@alum.mit.edu \
    --cc=git@vger.kernel.org \
    --cc=gitster@pobox.com \
    --cc=kevin@bracey.fi \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
Code repositories for project(s) associated with this public inbox

	https://80x24.org/mirrors/git.git

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).