Subject: Re: [PATCH/RFC] rebase -p: do not redo the merge, but cherry-pick first-parent changes

From: Johannes Sixt <[email-masked]>
Date: Fri, 25 May 2012 17:58:17 +0200

Am 24.05.2012 23:34, schrieb Junio C Hamano:
> Johannes Sixt <[email-masked]> writes:
> 
>> Today I was able to use rebase -i -p in the field. I used it to rebuild
>> an integration branch (akin to git's pu branch). Guess what? It did not
>> work as expected:
>>
>> Two of the topic branches' early parts were already merged in the
>> upstream. The instruction sheet had only 'pick' of merge commits for the
>> topics. Except for these two; there, all commits (that were not yet in
>> upstream) were offered to pick, including the merge commit.
>>
>> I started with this:
>>
>>     A--M--o--o   <- master
>>    /  /
>> --o--X--Y        <- side branch (partially merged in master)
>>    \     \
>>     R--S--N--T   <- integration (to be rebuilt on master)
>>
>> I wanted this:
>>
>>      A--M--o--o
>>     /  /       \
>>    /  /          R'--S'--N'--T'
>> --o--X--Y---------------´
> 
> It is unclear what exact revisions you gave to rebase, but I am assuming
> that you asked "rebase --onto master X^ T" (you can use R^ instead of X^;
> they refer to the same commit).

Sorry, I should have been more precise. The command was

  git rebase -i -p master T

An important detail is that the order of parents of N is S, Y. (I
assumed that this was somewhat clear from the context of my message.)

> It is straightforward to see what should happen to R and S; they should be
> a straight replay of single parent commit on top of 'master'.  
> 
> But it is unclear what should happen to X and Y.

Nothing. Relabel "integration" to "topic" in my artwork above. Then X
and Y are on an "unrelated side branch" that is merged into the topic
whose tip is at T. The early part of this side branch is already in
master.  In fact, if X were not merged into master, yet, then 'rebase -i
-p' already works as (I) intended: it leaves X and Y alone.

> When you are rebasing the X^..T sub-DAG, can you say what makes S more
> special than Y by looking at the original topology?  Your "I wanted this"
> picture depicts S' to be rewritten but Y stays the same.  Why?  

It is "not on topic" (pun intended). It is the second parent of N. Think
of X and Y as an independent bug fix sub-topic. It is merged into topic
only because T depends on the fix.

> They are both in the X^..T DAG, and neither of them is merged to 'master'.
> I can sort of see why X and R would be treated differently (X is part of
> master, R is not), but I cannot justify why your "I wanted this" picture
> replays S' without replaying Y'.
> 
> What am I missing?

First-parentship. When a topic or an integration branch is rebased (with
--preserve-merges), only the first-parent chain should be rewritten.

>> But I got this:
>>
>>     A--M--o--o-------Y'
>>    /  /       \       \
>> --o--X--Y      R'--S'--N'--T'
> 
> Which is what I would expect, from the "Y and S play a similar role in the
> sub-DAG X^..T in the original DAG, with respect to master" point of view.

-- Hannes