Subject: Re: Beyond Merge and Rebase: The Upstream Import Approach in Git

From: Junio C Hamano <[email-masked]>
Date: Wed, 12 Jul 2023 13:27:13 -0700

Junio C Hamano <[email-masked]> writes:

>> So I switched to a different scheme instead that I dub "merging rebase".
>> Instead of finishing the rebase with a merge, I start it with that merge.
>> In your example, it would look like this:
>>
>>    o---o---o---o---o  upstream/main
>>         \           \
>>          o---o---o---M---o'---o'---o' main
> ...
>> This strategy is not without problems, though, which becomes quite clear
>> when you accept PRs that are based on commits prior to the most recent
>> merging rebase (or rebasing merge, both strategies suffer from the same
>> problem): the _next_ merging rebase will not necessarily find the most
>> appropriate base commit, in particular when rebasing with
>> `--rebase-merges`, causing unnecessary merge conflicts.

In Git, any commit, be it a single parent commit or a merge, makes
this statement:

    I considered all the parents of this commit, and it is my belief
    that it suits the purpose of the branch I am growing better than
    all of them.

This is the foundation of the correctness of three-way merges.
Coming from a common ancestor, because M suits the purpose of the
branch better than M^1 or M^2, when merging anything forked from M^1
(or M^2) into a decendant of M (say, 'main'), as long as the
descendant of M still shares the same purpose of the branch, it does
not need to consider what the commits before M^1 (or M^2) did.

M in the "merging rebase", however, claims that M, i.e. the recent
upstream, fits the purpose of the branch better than the earlier
three commits did, which is not quite right.  In contrast, rebasing
merge does not have such a problem, i.e.

    o---o---o---o---o  upstream/main
         \           \
          \           a'---b'---c'
           \                     \
            a---b---c-------------M main

The commit c, a parent of M, implemented the features the topic
wanted to, and the commit c', another parent of M, implements the
same on top of a newer upstream.  The tree of M is the same as c'
and it matches the purpose, which presumably is to implement
whatever (a,b,c) or (a',b',c') wanted to on top of reasonably recent
upstream, of the branch.

Anyway, I do not think building on top of M would help from this
state, so let's stop seeing if there is a way to make rebasing merge
a bit more useful.

Thanks.