The situation that you describe requires that the history looks something like this:
--X--Y <-- your master
\
A--B--C--D <-- feature01
\
R--S--T <-- feature02
(Whether your master
has a commit Y
or is still at X
is irrelevant for the following.)
Why is that?
Notice that the two features have commits in common, A
in this example. When you do regular merges, Git knows about this fact and can deal with it without generating conflicts. In particular, in the second merge it will not pull in the changes made in A
again.
But when you do a squash merge of feature01
, you are generating this history:
--X--Y--F1 <-- your master
\
A--R--S--T <-- feature02
I truncated feature01
from the picture because it does not play a role anymore.
When you do a merge of feature02
now (squash or regular does not matter), Git attempts to apply commit A
again, because it does not have enough information to know that it has already merged it. The conflicts arise when one of the commits B
, C
, D
have made changes in the vicinity of the changes that A
did.
How to make merge --squash
work (subsequent merge works fine)?
You cannot. Do not use merge --squash
.
Of course, you can jump through some hoops by grafting history to pretend that A
was actually merged into F1
; but it is just a work-around, a band-aid for emergency cases, but that is too tedious for a regular workflow. And if you do that, why didn't you use a regular merge in the first place?