The answer by Ali Dowair links to the right discussions. But to best understand how to fix it I'd like to explain what is going wrong here first:
After your second merge your history looks something like this:
* master
|\
| * (F2) fixing commit on feature branch
* |
* | (R) revert of merge commit (M)
* |
* | (M) merge of feature into master
|\|
| * (F) faulty commit on feature branch
|/
* (B) common base commit
|
So, when you do a git merge feature
on the master
branch git
will look for the common base commit in those two branches and merge all changes from feature
committed since that base commit.
By the second time you git merge
d this base commit was F
with the faulty changes, i.e. F
was already included in master
and feature
and thus git
determined only F2
needed to be merged.
As the linked discussions in the answer by Ali Dowair say
So if you think of "revert" as "undo", then you're going to always miss this part of reverts. Yes, it undoes the data, but no, it doesn't undo history.
So since F
is already included in master
- as far as git
is able to detect this - it won't be merged again leaving you with two options (ignoring rewriting/force-pushing the history here):
- Revert the revert:
git revert R
right before you git merge feature
again. This will re-apply the previously merged and then undone changes - i.e. F
in this example - and then apply/merge the new changes from the feature branch:
* master
|\
| * (F2) fixing commit on feature branch
* | (R') revert of revert commit (R)
* |
* | (R) revert of merge commit (M)
* |
* | (M) merge of feature into master
|\|
| * (F) faulty commit on feature branch
|/
* (B) common base commit
|
- Rebase
feature
onto the new master
after the revert:
git checkout feature
git rebase B --onto master
# rebases all commits done since (B) onto the new master
git checkout master
git merge feature
Resulting in:
* master
|\
| * (F2') fixing commit on feature branch
* |
| * (F') faulty commit on feature branch
|/
*
|
* (R) revert of merge commit (M)
|
| * (F2) fixing commit on feature branch
| |
* | (M) merge of feature into master
|\|
| * (F) faulty commit on feature branch
|/
* (B) common base commit
|
Here git merge
will pull in the changes from F'
and F2'
which are the rebased versions of F
and F2
. Using --onto
here is necessary to stick to the original base commit B
here because just git rebase master
would omit F
for the same reasons git merge
would do.