Search code examples
gitmergerebase

Lost code after rebasing, in which merge is squashed


This is my current structure (a git log but without the text), the feature branch is branched from master:

D  <- Keep this
C  <- Squash/meld everything before into this
*
ME <- Merge commit
|\
| B
* |
* |
|/
A  <- First commit of the feature branch
MA <- master

I want to keep the last commit of the current feature branch D, and squash/meld everything before it into the second last commit C, like this:

D
C' <- Squash everything before C and C itself
MA

I then do a rebase with git rebase -i master:

  • The first commit A is kept, so I use pick. This will become C'.

  • Everything between A and C is squash.

    I see no merge commit ME, but all other commits are listed. According to this SO, merge commit will have everything in its branch, but with the message of B. B is listed, so this seems fine.

  • The last commit D is kept, so pick again.

While rebasing, I see a lot of conflicts. After checking, all the conflicts are resolved by accepting "incoming changes", as it contains newer code.

However, after rebasing, the code no longer compiles, it is a mess now. I realize that the code in the merge commit ME is lost. ME is not a trivial merge, I have to resolve a lot of conflicts before merging.

I then tried to do a rebase in which I'll pick all the commits. I think it should proceed without any conflict, and leave the history intact (or recreating the exact same history). But git complains that there are conflicts, and the conflicts are exactly the same as the ones in the above interactive rebase session.

How should I do my rebase?


Solution

  • Here is one way to do it :

    • Run git rebase -i HEAD~2

    • The sequencer script should mention C and D:

      Set C action to edit, save and close

    • The rebase will apply C and pause.

      At this point, run git reset --soft MA, followed by git commit (this will squash MA..C in one single commit)

    • Now proceed with the rebase: git rebase --continue