Hi Junio, On Fri, 19 Jan 2018, Junio C Hamano wrote:
> Johannes Schindelin <johannes.schinde...@gmx.de> writes: > > > Think of --recreate-merges as "--preserve-merges done right". It > > introduces new verbs for the todo list, `label`, `reset` and `merge`. > > For a commit topology like this: > > > > A - B - C > > \ / > > D > > > > the generated todo list would look like this: > > > > # branch D > > pick 0123 A > > label branch-point > > pick 1234 D > > label D > > > > reset branch-point > > pick 2345 B > > merge 3456 D C > > Yup. I've seen this design talked about on list in the past, and > I've always felt that this is "sequencer done right". > > At the first glance, it may feel somewhat unsatisfying that "merge" > has to say effects of which commits should be reflected in the > result and which commot to take the log message from, i.e. > (recreated)D is merged to form the resulting tree, and 3456=C is > used for the log, to recreate C in the above example, while "pick" > always uses the same commit for both, i.e. recreated B inherits both > the changes and log message from the original B=2345 (or depending > on the readers' point of view, "merge" is allowed to use two > different commits, while "pick" is always limited to the same one). > > But I think this distinction is probably fundamental and I am not > opposed to it at all. The result of "pick" has only one parent, and > the parent is determined only by the previous actions and not by > anything on the "pick" line in the todo list. But the result of > "merge" has to record all the other parents, and only the first > parent is determined implicitly by the previous actions. We need to > tell the "merge" command about "3456=C" in order to recreate the > effect of original merge commit (i.e. changes between B and C) as > well as its log message, and we also need to tell it about label "D" > that it is the "other parent" that need to be recorded. Yes, this was the hard lesson of the failed preserve-merges design. > Obviously "merge" command syntax should allow recreating an octopus, > so whenever I said "two" in the above, I meant "N". The original > merge commit is needed so that the effect to replay (roughly: a > patch going to the original merge result from its first parent) can > be learned from the existing history, and all the other "N-1" > parents needs to be given (and they must have been already created > in the todo list) so that the resulting recreated merge can be > recorded with them as parents (in addition to the first parent that > is implicitly given as the result of all the previous steps). I have two more patch series lined up after this one, the first one implements --root via the sequencer, and the second one indeed extends `merge` to handle octopus commits. > One interesting (and probably useful) thing to notice is that if A > were not rebased in the above sample picture, and only B were the > one that was tweaked, then a recreated C may use the same original D > as its side parent, and the mechanism outlined above naturally can > support it by allowing an un-rewritten commit to be given as a side > parent when "merge" is redoing C. I think that you will get a kick out of reading the commit message of the last commit, as it does talk about the problematic C: it *would* be rebased by default. In the next iteration I will actually switch around the default from rebase-cousins to no-rebase-cousins for that reason. Ciao, Dscho