Simplified, this is what happened to us:
Start with this file on master
:
class SomeClass {
...
}
Create branch featureA
off `master.
On featureA
, change file to:
class SomeClass {
...
}
extension SomeClass {
// implement feature A
}
featureB
off `master.On featureB
, change file to:
class SomeClass {
...
}
class OtherClass {
// implement feature B
}
featureB
into master
.featureA
into master
.What we expect is:
class SomeClass {
...
}
extension SomeClass {
// implement feature A
}
class OtherClass {
// implement feature B
}
or the two additions in reverse order, that's fair.
Realistically, Git should probably report a conflict: it has no knowledge about semantics, and the two "simultaneous" changes can not be reconciled.
What we get is:
class SomeClass {
...
}
class OtherClass {
// implement feature B
}
without a conflict. That is, the later commit (that was merged before the other) wins out, silently.
Can this be prevented? How?
Note: If I try this in a clean repo with the steps above, I get a merge conflict in the last step. So either the issue was rooted in something else we did on the repo; hints appreciated, I don't see what could have affected things. Or the problem is the diff algorithm being tripped up by more complicated code; in the production Swift code, we had two extensions on one side, and an enum with nested types on the other side.
Some cross-testing with the same attempted merge:
git merge
and git merge -s patience
.On Mac with Git 2.11.0 and Meld 3.16.0, I see no conflicts with either merge command.
Instead, there's
==== BASE ====
}
==== BASE ====
at the end of the file, so I think Meld is not parsing the diff correctly here.
It seems as if that version of Meld has trouble parsing some diffs. It didn't show me the conflict, so I didn't fix it properly before marking it as resolved.
Nota bene: reproducing this apparently needs more "matching" lines; the small example from my question doesn't do it.