Hi Johannes, Johannes Schindelin <Johannes.Schindelin@xxxxxx> writes: > Hi Buga, > > thank you for making this a lot more understandable to this thick > developer. > > On Tue, 27 Feb 2018, Igor Djordjevic wrote: > >> On 27/02/2018 19:55, Igor Djordjevic wrote: >> > >> > It would be more along the lines of "(1) rebase old merge commit parents, >> > (2) generate separate diff between old merge commit and each of its >> > parents, (3) apply each diff to their corresponding newly rebased >> > parent respectively (as a temporary commit, one per rebased parent), >> > (4) merge these temporary commits to generate 'rebased' merge commit, >> > (5) drop temporary commits, recording their parents as parents of >> > 'rebased' merge commit (instead of dropped temporary commits)". >> > >> > Implementation wise, steps (2) and (3) could also be done by simply >> > copying old merge commit _snapshot_ on top of each of its parents as >> > a temporary, non-merge commit, then rebasing (cherry-picking) these >> > temporary commits on top of their rebased parent commits to produce >> > rebased temporary commits (to be merged for generating 'rebased' >> > merge commit in step (4)). >> >> For those still tagging along (and still confused), here are some >> diagrams (following what Sergey originally described). Note that >> actual implementation might be even simpler, but I believe it`s a bit >> easier to understand like this, using some "temporary" commits approach. >> >> Here`s our starting position: >> >> (0) ---X1---o---o---o---o---o---X2 (master) >> |\ >> | A1---A2---A3 >> | \ >> | M (topic) >> | / >> \-B1---B2---B3 >> >> >> Now, we want to rebase merge commit M from X1 onto X2. First, rebase >> merge commit parents as usual: >> >> (1) ---X1---o---o---o---o---o---X2 >> |\ |\ >> | A1---A2---A3 | A1'--A2'--A3' >> | \ | >> | M | >> | / | >> \-B1---B2---B3 \-B1'--B2'--B3' >> >> >> That was commonly understandable part. > > Good. Let's assume that I want to do this interactively (because let's > face it, rebase is boring unless we shake up things a little). And let's > assume that A1 is my only change to the README, and that I realized that > it was incorrect and I do not want the world to see it, so I drop A1'. > > Let's see how things go from here: > >> Now, for "rebasing" the merge commit (keeping possible amendments), we >> do some extra work. First, we make two temporary commits on top of old >> merge parents, by using exact tree (snapshot) of commit M: >> >> (2) ---X1---o---o---o---o---o---X2 >> |\ |\ >> | A1---A2---A3---U1 | A1'--A2'--A3' >> | \ | >> | M | >> | / | >> \-B1---B2---B3---U2 \-B1'--B2'--B3' > > Okay, everything would still be the same except that I still have dropped > A1'. > >> So here, in terms of _snapshots_ (trees, not diffs), U1 = U2 = M. >> >> Now, we rebase these temporary commits, too: >> >> (3) ---X1---o---o---o---o---o---X2 >> |\ |\ >> | A1---A2---A3---U1 | A1'--A2'--A3'--U1' >> | \ | >> | M | >> | / | >> \-B1---B2---B3---U2 \-B1'--B2'--B3'--U2' > > I still want to drop A1 in this rebase, so A1' is still missing. > > And now it starts to get interesting. > > The diff between A3 and U1 does not touch the README, of course, as I said > that only A1 changed the README. But the diff between B3 and U2 does > change the README, thanks to M containing A1 change. > > Therefore, the diff between B3' and U2' will also have this change to the > README. That change that I wanted to drop. > >> As a next step, we merge these temporary commits to produce our >> "rebased" merged commit M: >> >> (4) ---X1---o---o---o---o---o---X2 >> |\ |\ >> | A1---A2---A3---U1 | A1'--A2'--A3'--U1' >> | \ | \ >> | M | M' >> | / | / >> \-B1---B2---B3---U2 \-B1'--B2'--B3'--U2' > > And here, thanks to B3'..U2' changing the README, M' will also have that > change that I wanted to see dropped. > > Note that A1' is still dropped in my example. > >> Finally, we drop temporary commits, and record rebased commits A3' >> and B3' as our "rebased" merge commit parents instead (merge commit >> M' keeps its same tree/snapshot state, just gets parents replaced): >> >> (5) ---X1---o---o---o---o---o---X2 >> |\ |\ >> | A1---A2---A3---U1 | A1'--A2'--A3' >> | \ | \ >> | M | M' >> | / | / >> \-B1---B2---B3---U2 \-B1'--B2'--B3' > > Now, thanks to U2' being dropped (and A1' *still* being dropped), the > change in the README that is still in M' is really only in M'. No other > rebased commit has it. That makes it look as if M' introduced this change > in addition to the changes that were merged between the merge parents. Except that original proposal suggests to cosider this a conflict and to stop for amendment, as U1' and U2' now differ. -- Sergey