Scenario:
git commit -m "Step1"
git commit -m "Step2"
git commit -m "Step3"
git pull
# merge a lot of changes from upstream, resolve conflictsgit commit -m "Step4"
git commit --fixup <Step2>
Now I have a separate fixup commit. How could I squash back that one fixup without destroying the merge history?
So I need something around the following:
git reset --hard <Step3>
git cherry-pick <fixup! Step2>
git rebase --autosquash <Step1>
git merge <same upstream commit-id> # resolve the same conflicts again!
git cherry-pick <Step4>
In other words: go to a commit just before the merge. Cherry-pick all fixups. Autosquash. Redo merge. cherry-pick all commits after the merge.
Is there an easier way to do all of this automatically?
Update. My recipe which sounds like that it should be reliable enough.
<fixup! Step2>
right after the merge commit.<Step 3>
<fixup! Step2>
--no-commit
the same upstream commitgit checkout <fixup! Step2> .
<Step4>
It works, linear approach, no conflicts to re-resolve, but quite cumbersome if done manually. Will try to use/adapt the @jthill script suggested in the comment...
I wonder if this is so uncommon scenario that it was not implemented out of box... For me it occurs quite often.
Ok... you will have to redo the merge but you can avoid having to redo solving the conflicts with a little trick: prepare a commit that has the content of the merge commit applying the fixup.... so, something like:
git checkout -b template the-merge-commit
git cherry-pick the-fixup-commit # apply the change of the fixup
Now, run the rebase you want to run (with --rebase-merges
) and when you get the conflicts on the merge commit, simply do:
git restore --worktree --stage --source template -- .
# ready to move on
git rebase --continue
That should do.
Another way would be running the rebase (with --rebase-merges
) and then, when you get the conflict you can pull the content of the original commit and you can apply the changes from the fixup by hand
git rebase --rebase-merges blah blah
# when you hit the conflict on the rebase
git restore --worktree --source REBASE_HEAD -- . # bring everything from the original merge commit
git show the-fixup-change | git apply - # apply changes of the fixup by hand
git add . # add everything to the index
git rebase --continue