We are all familiar with a git merge conflict which is triggered when two engineers modify the same line or block of code. Git merge conflicts occur when two conflicting changes have been made on the same line of code in a file.
Git will keep engineers from merging a pull request with line-level conflicts; although it will not keep you from accidentally claiming a merge is complete and pushing up to CI code riddled with merge conflict annotations.
Git, however, cannot detect logical merge conflicts.
A logical merge conflict is created when two separate changes are made to a repository that when combined collide to create a logical breakage. Logical merge conflicts can lead to broken tests and even broken builds.
This can trivially occur when one engineer in pull request A renames a method ‘Foo’ to ‘Bar’ and another engineer in a separate pull request B adds new code that calls ‘Foo’. If these two pull requests are not tested against each other, they will both merge and break the main branch. A logical merge conflict can similarly lead to broken tests (without breaking compilation).
Let’s walk through a simple example:
Our main branch is almost as trivial (and contrived) as it gets. Two simple assignment operators both setting ‘a’ and ‘b’ to 1.
Eli adds an assertion on line 3
David changes the value of ‘a’ to 0 on line 1
Both Eli and David land their changes
Git has no problem allowing each of these changes to merge. There is no direct line-level conflict and each change is independently correct.
Of course, once both changes are merged into the main branch the repository is completely broken. The change to line 1 is in logical conflict with line 3. Even worse, this broken state, will probably only be discovered hours or days later by a third engineer who is dumbfounded as to why their pull request is failing in seemingly unaffected code.
The above example is obviously contrived, but in practice, any active organization with more than a handful of engineers working together will invariably run into logical merge conflicts.
The industry solution to this problem is adding a merge service in the loop to protect your main branch from these harder-to-find conflicts. Luckily we happen to have built one — Trunk Merge.