gitmergegit-rebase

Looking for a clean way to reword a few commits from before multiple merges were done without having to re-resolve conflicts


Note: I have already looked at the following answers and they don't seem to apply or work in the way I expect them to work:

I am working with a development branch where several people collaborated on a new feature before we want to merge it back to master. I did the initial work and have several commits with very bad commit messages that I want to squash into one and then write an appropriate message. The master branch has already been merged into the dev branch, so we are fully up to date with master already.

I am fairly well acquainted with the standard rebase operation, but I have never had to deal with rebasing merges before. Following the above links, I tried doing an interactive rebase onto master while rebasing merges using the command rebase -i -r origin/master. I was then given a fairly straightforward list of commits with a couple of merge commands interspersed throughout.

After doing the standard reword and fixup to the commits I wanted, I then saved the plan and discovered that it is asking me to resolve the conflicts again at each merge. I must be completely misunderstanding how this works, because I thought that it would just replay the merge exactly as I had done it, since I am not changing any code to create any new conflicts.

Why is this happening, and how can I clean up this commit history without having to go through a painful merge 3 times again?

This is the tree I'm working with.

*   ca0e36a Merge remote-tracking branch 'origin/master' into DEV/FeatureBranch
|\
| * Master Branch Commit
| * Master Branch Commit
| * Master Branch Commit
| * Master Branch Commit
| * Master Branch Commit
| * Master Branch Commit
| * Master Branch Commit
* | b5e3349 Feature Branch Commit
* | f3348b1 Feature Branch Commit
* | 92ff49b Feature Branch Commit
* | 43972d9 Feature Branch Commit
* | 603a759 Feature Branch Commit
* | b2d2ace Feature Branch Commit
* | 2e247cf Feature Branch Commit
* | efd8954 Feature Branch Commit
* | 872fd02 Feature Branch Commit
* | 9652ecd Squash this
* | cd1561f Reword this
* | 27379f8 Merge remote-tracking branch 'origin/master' into DEV/FeatureBranch
|\|
| * 67df667 Commit on Master
* | c5dc9aa Merge remote-tracking branch 'origin/master' into DEV/FeatureBranch
|\|
| * 6bcb1c5 Commit on Master
| * 2a63706 Commit on Master
| * 9ce26be Commit on Master
| * d3aab96 Commit on Master
| * 9bfd6e0 Commit on Master
| * a136376 Commit on Master
| * a23ea9a Commit on Master
| * b26c01a Commit on Master
| * 04356b3 Commit on Master
* | 31f6717 Squash this commit
* | 56724e4 Squash this commit
* | 1eb2fc5 Squash this commit
* | 40c8941 Squash this commit
* | 2ac7ee3 Squash this commit
* | d9d7e1b Reword this commit
|/
* 7b56d07 Start of branch

Solution

  • If you only want to reword without any content change in the files (and you are not changing the base), you can use this every time you hit a conflict:

    git restore --worktree --stage --source=REBASE_HEAD -- .
    

    That will get the content of the files as they are on the original commit being rebased (you are not introducing any changes of files so it should be good).

    Then you can run git rebase --continue and wait for the next conflict.

    Warning: For this recipe, it is very important that in your rebase you are actually not changing the base. If you are, then changes between the 2 bases (old base vs new base) will be lost when you do the restore.