Hi Elijah, On Tue, 7 Sep 2021, Elijah Newren wrote: > On Tue, Sep 7, 2021 at 11:51 AM Johannes Schindelin > <Johannes.Schindelin@xxxxxx> wrote: > > > > On Thu, 2 Sep 2021, Johannes Sixt wrote: > > > > > Am 02.09.21 um 16:18 schrieb Johannes Schindelin: > > > > On Wed, 1 Sep 2021, Junio C Hamano wrote: > > > >> A good goal. There is no remaining use case where (a fictitious and > > > >> properly working version of) "--preserve-merges" option cannot be > > > >> replaced by "--rebase-merges", is it? I somehow had a feeling that > > > >> the other Johannes (sorry if it weren't you, j6t) had cases that the > > > >> former worked better, but perhaps I am mis-remembering things. > > > > > > > > I think that I managed to address whatever concerns there were about the > > > > `--rebase-merges` backend in the meantime. > > > > > > That was either my suggestion/desire to make no-rebase-cousins the > > > default. That has been settled. > > > > > > Or my wish not to redo the merge, but to replay the first-parent > > > difference. The idea never got traction, and I've long since abandoned > > > my implementation of it. > > > > Thank you for clarifying. > > > > Yes, I remember how that idea came up, and I even tried that strategy for > > a couple of merging rebases of Git for Windows' branch thicket. Sadly, it > > did not work half as well as I had hoped. > > > > The best idea I had back then still is in want of being implemented: sort > > of a "four-way merge". It is basically the same as a three-way merge, but > > allows for the pre-images to differ in the context (and yes, this cannot > > be represented using the current conflict markers). Definitely not > > trivial. > > merge-ort opens a new possibility (since it does merges without > touching the index or working tree): Take the merge commit, M, that > you are trying to transplant. Hold on to it for a minute. Do what > rebase-merges does now; namely, do a simple merge of the desired new > branches that otherwise ignores M to get your new merge commit N. > Hang on to N too for a minute. Now use merge-ort to auto-remerge M > (much like AUTO_MERGE or --remerge-diff does) to get a new merge > commit that we'll call pre-M. If M was a clean merge that the user > didn't amend, then pre-M will match M. If M wasn't a clean merge or > was amended, then pre-M will otherwise differ from M by not including > any manual changes the user made when they originally created M -- > such as removing conflict markers, fixing semantic conflicts, evil > changes, etc. > > Now we've got three merge commits: pre-M, M, and N. (Technically, > pre-M and N might be toplevel trees rather than full commits, but > whatever.) The difference between pre-M and M represent the manual > work the user did in order to create M. Now, do a three-way > (non-recursive) merge of those commits, to get the rebased result, R. > This operation has the affect of applying the changes from pre-M to M > on top of N. > > There's obviously some edge cases (e.g. nested conflict markers), but > I think they're better than the edge cases presented by the > alternatives: > * the first-parent difference idea silently discards intermediate > changes from reapplying other patches (especially if other patches are > added or dropped), which to me feels _very_ dangerous > * the current rebase-merges idea silently discards manual user > changes within the original merge commit (i.e. it hopes that there is > no difference between pre-M and M), which can also be lossy > * I don't think this idea drops any data, but it does run the risk > of conflicts that are difficult to understand. But I suspect less so > than your five-way merge would entail. > > If the difficulty of conflicts in this scheme is too high, we could do > a few things like providing multiple versions (e.g. if either > pre-M:file or N:file had conflicts, or maybe if R:file has nested > conflicts, then place both R:file and N:file in the working tree > somewhere) or pointing at special commands that help users figure out > what went on (e.g. 'git log -1 --remerge-diff M -- file'). While I agree that `merge-ort` makes a lot of things much better, I think in this context we need to keep in mind that those nested merge conflicts can really hurt. In my tests (I tried to implement a strategy where a 3-way merge is done with M and N^, using the parent commits of M as merge parents successively, see https://lore.kernel.org/git/nycvar.QRO.7.76.6.1804130002090.65@xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx/ for the nitty gritty), I ran into _nasty_ nested merge conflicts, even with trivial examples. And I came to the conviction that treating the merge conflict markers as Just Another Line was the main culprit. I wish I had the time to try out your proposed strategy with the conconcted example I presented in that mail I linked above. Because now I am curious what it would do... Ciao, Dscho