2

In a git repository, I have a branch in which I have regularly merged the master branch:

A -- B -- C -- D -- E -- F -- G (master)
 \         \              \ 
  U -- V -- M1-- X -- Y -- M2 -- Z  (feature)

Where the M1 and M2 commits merge master into feature.

I would like to squash the consecutive commits U and V and preserve the rest of the structure.

Intuitively, it should be possible to do this without having to solve the merge conflicts in M1 and M2 again, because by squashing U and V together I do not change the states of the working trees being merged by M1, nor the merge base.

However, if I do this with git rebase -i A --rebase-merges (with pick U followed by fixup V) I need to solve the merge conflicts of M1 again.

Is there a way to instruct Git to re-use M1 and the following commits as-is?

pintoch
  • 2,293
  • 1
  • 18
  • 26
  • "Intuitively, it should be possible to do this without having to solve the merge conflicts in M1 and M2 again" No it shouldn't. You can't "reuse" commits. Git commits are immutable, including their parentage. So all commits after the squash, including the merge commits, must be replaced by entirely new commits constructed by Git. So the merges must be performed again. `rerere` can help with repeating the same merge conflict resolution but it probably won't help you now because you didn't turn it on. You just have to suck it up and resolve the conflicts again. – matt Aug 31 '23 at 13:28
  • I understand that those commits will get new ids, but what I mean is that the state of the working tree in those commits should be identical to that of the corresponding commits before the rebase. – pintoch Aug 31 '23 at 13:30
  • “Intuitively, it should be possible to do this without having to solve the merge conflicts in M1 and M2 again”—Conceptually yes, and `git rebase --rebase-merges` might get that capability at some point. But as it is currently implemented I think it applies the commits and doesn't care about “previous” resolutions. – Guildenstern Aug 31 '23 at 13:31
  • Yup, and you will have to resolve any conflicts in order to construct that. – matt Aug 31 '23 at 13:31
  • 1
    See https://stackoverflow.com/questions/49500943/what-is-git-rerere-and-how-does-it-work – matt Aug 31 '23 at 13:32
  • 1
    Ideally one would use a snapshot-based rewriting tool for this since all you need to do is to create new commits with different parents: change the parent of `V` from `U` to `A` and then recalculate the transitive children. `git rebase` isn't great for this use-case (and slow anyway). – Guildenstern Aug 31 '23 at 13:36

0 Answers0