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.

Original source

Related problems