Search code examples
gitmergegit-mergegit-merge-conflict

Git silently merges as updates what should be conflicts


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
    }
    
  • Create branch featureB off `master.
  • On featureB, change file to:

    class SomeClass {
        ...
    }
    
    class OtherClass {
        // implement feature B
    }
    
  • Merge featureB into master.
  • Merge 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.


Solution

  • Some cross-testing with the same attempted merge:

    • On Ubuntu with Git 2.7.4 and Meld 3.14.2, I see conflicts with 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.

    • On the same Mac and during the same merge, the diff viewer in AppCode 2017.3 shows a conflict.

    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.