On Fri, Apr 15, 2022 at 10:41 PM Edmundo Carmona Antoranz <eantoranz@xxxxxxxxx> wrote: > > On Fri, Apr 15, 2022 at 10:33 PM Junio C Hamano <gitster@xxxxxxxxx> wrote: > > > > It would be wonderful if a single command like replay can be used to > > say "In the old history master..seen I have bunch of merges. master > > used to be M but now it is at N. Rebuild M..S on top of N _but_ > > with a bit of twist. Some of the topics in M...S may have been > > merged to 'master' between M..N and the replayed history on top of N > > does not want to have a merge from such 'already graduated' topics. > > Many topics are updated, either by adding a new commit on top or > > completely rewritten, and we want an updated tip of these topic > > branches, not the old tip that I merged when I created M..S chain, > > when replaying the history on top of N." > > > > That kind of operation is quite different from what "rebase" does, > > and deserves to be under a different name. > > > > Let me work a little bit on your workflow to see what I can do. Replaying merges is something I've put a little thought into, so allow me to provide some pointers that may help. Merges need special handling for replaying, and in my opinion, doing either just a new merge of the new trees (what rebase --rebase-merges does), or just reusing existing trees (what you proposed to start this thread) are both suboptimal, though the former is likely to just be annoying and require potentially unnecessary user refixing, whereas the latter can silently discard changes or reintroduce discarded changes and could be dangerous. More details on both of these... An important part about merges is they may have resolved conflicts -- both textual (the standard conflict markers people have to resolve) and semantic (e.g. one person changes the API of some function, and the other branch being merged adds a caller of that function, so the merge has to modify the new caller to use the new API). We do not just want to do a new merge and re-use the commit message (as rebase --rebase-merges does), for two reasons: (1) the user either has to re-resolve the textual conflict resolutions by hand, or use rerere which requires a working tree (and we'd like replays to proceed without a working tree where possible), and (2) it tosses semantic merge conflict resolutions entirely. We also do not just want to use existing trees as-is (as you started with in your patch), for three reasons: (1) when we move to a new base the new merge needs to include the changes from the newer base, (2) the topic might have additional changes added (or removed) during the "rebase" which need to be reflected in the merge as well, and (3) the merge may have had additional changes stuffed directly into it to solve semantic conflicts which we want "ported" to the new merge commit. So, for handling merges, we should avoid both of these overly simplistic mechanisms, and do something that tries to handle forward-porting these conflict resolutions. I have outlined steps to do so at https://lore.kernel.org/git/CABPp-BHp+d62dCyAaJfh1cZ8xVpGyb97mZryd02aCOX=Qn=Ltw@xxxxxxxxxxxxxx/ > Tip: It will probably come out in the shape of a script. We can talk about > what to do with it later. Note that we've worked hard to replace scripts with builtins in git, especially in the case of rebase. Scripts are great for prototyping, and I fully support that, but I'd rather that scripts remained a prototype. I'd be sad to see us regress and return to scripts for rebase. > > Compared to that, "replay exactly the same set of commits in the > > same shape on top of a different commit whose tree happens to be the > > same as the original", is a mere special case of "rebase" that is > > not all that interesting. It may be a worthwhile thing to do to > > teach "rebase" capable of doing so reliably and more efficiently, > > but that still falls into "improving rebase" category, not meriting > > a separate command. > > I agree that it might not require a full separate command. I'll see if > I am able to get it into rebase. If you'd like to try out some of the ideas in the link above for handling replaying of merges, feel free. I've done a little bit of playing with this idea, and would be especially interested to learn of any new testcases or challenges you come up with. I think a full implementation requires changes to the merge machinery (at each of the merge-ort.c, ll-merge.c, and maybe even xdiff/ levels), on top of the merge machinery changes being driven by the merge-tree changes. [1] https://lore.kernel.org/git/CABPp-BGW39_5r8Lbt3ymR+F_=hWJcf=2e7O75vFNJ=3CEL5s=g@xxxxxxxxxxxxxx/ I'd also like to mention that I have a git-replay command, as mentioned previously at various places (see [2,3,4,5,6,7] and probably elsewhere). It's far from complete (I was busy with sparse-checkout, merge-tree, etc., and then disappeared for over a month on top of that), but I still intend to complete it. I would like it to cover several usecases, including better replaying of merges, and I think usescases like the one Junio points out here should be in scope. If you'd like to play around with my git-replay (not even alpha quality yet, though it can do some things), feel free to take a look: https://github.com/newren/git/tree/replay [2] https://lore.kernel.org/git/nycvar.QRO.7.76.6.2110211147490.56@xxxxxxxxxxxxxxxxx/ [3] https://lore.kernel.org/git/CABPp-BH_TiJaDpn2+VVjCb83NEFjL9teSk06+YiZyFGiTu8Lpg@xxxxxxxxxxxxxx/ [4] https://lore.kernel.org/git/CABPp-BHpK8hPsiuHoYsf5D_rjcGLSW-_faL3ODoh56pG_2Luwg@xxxxxxxxxxxxxx/ [5] https://lore.kernel.org/git/CABPp-BFQv+mrWj8iH0Vo5Pr5L922v=ZsVthFjofy5pm1Sx8x5Q@xxxxxxxxxxxxxx/ [6] https://lore.kernel.org/git/CABPp-BE+DaBkis0r7pqs-kaChCvFhCEsyDg=gs3=QjWOPERaXQ@xxxxxxxxxxxxxx/ [7] https://lore.kernel.org/git/pull.1122.v5.git.1645340082.gitgitgadget@xxxxxxxxx/