On Sun, Apr 17, 2022 at 5:30 AM Edmundo Carmona Antoranz <eantoranz@xxxxxxxxx> wrote: > > On Sun, Apr 17, 2022 at 7:05 AM Elijah Newren <newren@xxxxxxxxx> wrote: > > > > > > 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/ > > > > Hey, Elijah! Thanks for taking the time and the feedback. > > Forget about me introducing replay as a separate command as a "real" > proposal. My intent (and which I saw most simple to be able to show > it) was to present the idea of an optimization (if you will) to the > rebase mechanism under certain rather narrow conditions: > > git rebase --onto A B C > > if A^{tree} == B^{tree} that means that we could create an equivalent > commit for the segment B..C on top of A without much hassle by reusing > the same trees from that segment (no need to calculate new trees...and > no need to move along the working tree as we are creating those > commits). > > My impression from reading your feedback is that you have a much > broader scope in terms of what you want to achieve.So, for the time > being, I will work on trying to get the optimization in rebase and see > how far I am able to move it forward.... and you are able to keep > replay as a separate command if that is your will for the > not-so-distant future. :-) My (Git-compatible) VCS [1] is very relevant to this thread. It always treats the contents of a merge commit as the diff compared to the re-merge (auto-merged) parents. That applies to diffs (like --remerge-diff) and rebases (what Elijah suggested in that link above) . An important part of the solution I went with is to store information about conflicts in the commits. Note that it's a more high-level representation of the conflicts - not conflict *markers* - that's stored in the commits [2]. Adding a new kind of object type is obviously a huge step to take for Git, but perhaps you can consider it as long as these objects are not exchanged. Also, as you have probably noticed with your `git replay` command, this kind of rebasing without touching the working copy or trees can get pretty fast. I didn't see any performance numbers in your original message, but you are probably able to rebase >1k commits per second in the git.git repo [3]. [1] https://github.com/martinvonz/jj [2] https://github.com/martinvonz/jj/blob/main/docs/technical/conflicts.md [3] https://github.com/martinvonz/jj/discussions/49