How to rebase after a merge?
git, git-merge, git-rebase
Solution
Consider the following Git graph:
A...C...D...F
^ ^ ^ master
\ \
G...H...I...J
^ feature
The ... means "lots of commits".
Suppose we want to essentially rebase, i.e. take the commits in feature's history but not in master's history and reform them as a linear sequence of commits in master. This confounded by the fact that we merged master into feature at commit `I`. If we try to rebase, Git screws up because it tries to apply e.g. `C` on top of master and finds conflicts.
The best method is from this answer, copied below for convenience:
git checkout feature
git branch -m feature-old
git checkout main
git checkout -b feature
git merge --squash feature-old
git commit
We can solve this problem by grabbing the actual changes from `feature` and packing them into a new commit. Here's a way to do this using only very basic Git commands:
(1) git checkout feature
(2) git merge master
(3) git reset A
(4) git add -A # This stages all working copy changes
(5) git commit -m "Every change between A and J"
In step (2), the `feature` branch has all changes in both `master` and `J`. After step (3), HEAD points at `A`, but our working copy has all the changes from `master` and `J`, and steps (4) and (5) stage and commit those changes.
At this point our graph looks like this
A...C...D...F
^ ^ master
\
J'
^ feature
Note that `J'` contains everything in `A...F`. Now we do
git rebase master
Git happily applies the changes in `J'` as a new commit `J''`, but the only changes to add are those in `G...J` because the other changes are already in master. So now we have
A...F<--J''
master^ ^feature
with all of the changes in our `feature` branch squashed into commit `J''`. At this point, you can reset to `F` and re-apply changes in `J''` in a more granular fashion (even using `git add --patch`) if you want.
Another way to do essentially the same thing is with `read-tree` as explained in this other answer
git checkout master
git read-tree -u -m feature
Yet another way to do the same thing, stolen from this answer, is
git diff master > feature.patch
git checkout master
patch -p1 < feature.patch
Problem
We have a sequence of events like this: - Create branch A, and add a few commits to it - Time passes, hundreds of commits added to master - Master is merged into A - Time passes, maybe another 50 commits added to master Is it possible to turn the merge in step 3 into a rebase? If nothing else, it would make the impending merge simpler as there would be less history to look at. We haven't had rerere enabled.