git rebase already merged branch?

So if you haven't made your changes to master and you don't mind rewriting history of master, there is a way to do this – but when you are rebasing you are rewriting history, so make sure you know what you are doing first.

If you are certain this is the direction you want to take your history, you should start by checking out the master branch and interactively rebasing it (git rebase -i) onto the commit where feature was cut from (in your case, [M2]).

Prior to your rebase, your history should look like this (as per your original problem):

        [F1]-[F2]-[F3]         -- Feature Branch
       /   \
[M1]-[M2]-[F1]-[M3]-[M4]       -- Master Branch

Once you start your interactive rebase, you should see the following actions:

pick hash_f1 [F1]
pick hash_m3 [M3]
pick hash_m4 [M4]

You will want to drop the first commit, the merged contents of feature prior to commits [F2] and [F3], so that master can replay the changes without [F1] in it. Note that you will not lose the [F1] commit, because it will still be in feature's history.

Rebasing should give you this history:

        [F1]-[F2]-[F3]         -- Feature Branch
       /
[M1]-[M2]-[M3]-[M4]            -- Master Branch

master has all M commits, and feature has all F commits, still cut from [M2]. From there it's a simple merge to get feature back into master:

git merge --no-ff feature

And voilà – you've got what you want:

        [F1]-[F2]-[F3]         -- Feature Branch
       /             \
[M1]-[M2]-[M3]-[M4]-[F*]       -- Master Branch

Again, be very careful that this is what you want to do, as rewriting history can be dangerous. That said, it is definitely worth it to do it locally.

Also, this process can be extended to any refs, not just a feature and master branch, so there are further cases where this may make more sense. In my opinion, a stable branch like master should typically not be able to have its history rewritten, but each Git environment and workflow is different, so really there are no rules which cannot be rewritten.


As correctly stated, no need for rebase.

For the last part of question:

"if I do git rebase first, won't the [F1] commit be in both the branches"

F1 commit would have been ommited if you proceeded with rebase.

According to https://git-scm.com/docs/git-rebase

If the upstream branch already contains a change you have made (e.g., because you mailed a patch which was applied upstream), then that commit will be skipped. For example, running git rebase master on the following history (in which A' and A introduce the same set of changes, but have different committer information):

      A---B---C topic
     /
D---E---A'---F master

will result in:

               B'---C' topic
              /
D---E---A'---F master

You don't have to rebase. You can just do the merge. Rebasing creates a very clear history, but it is actually not a faithful representation of the history. Merging is safer, it is more straightforward, and it results in a true representation of the actions of developers.

People who come to git from other version control systems often dislike the complicated branching and merging history of git, so some of them are overusing the rebase feature. This takes extra effort, it fails more often than "merge", and it results in a false view of the history.

I'm not saying you should never use rebase, but as a rule of thumb I'd say the default should be to use "merge", and use rebase only when you really want to rewrite history.

One example of why rebase is useful is: Suppose you're making lots of incremental commits, and adding and reverting stuff on your local repository. Before you push to the global repository, you decide you want the other team members to see your contribution as a cleaner, single commit, taking out everything that's irrelevant. Then you use "interactive rebase" to consolidate your commits and improve the commit message, before pushing.