Wednesday, December 16, 2015

When 768 conflicts equals zero conflicts

While reading the completely fascinating Move Fast and Fix Things, I came across this spectacularly delicious tidbit:

A much more interesting case happened when a merge that was clearly a conflict in libgit2 was being merged successfuly by Git. After some debugging, we found that the merge that Git was generating was broken — the single file that was being merged was definitely not a valid merge, and it even included conflict markers in the output!

It took a bit more digging to find out the reason why Git was "successfully" merging this file. We noticed that the file in question happened to have exactly 768 conflicts between the old and the new version. This is a very peculiar number. The man page for git-merge-one-file confirmed our suspicions:

The exit value of this program is negative on error, and the number of conflicts otherwise. If the merge was clean, the exit value is 0.

Given that shells only use the lowest 8 bits of a program's exit code, it's obvious why Git could merge this file: the 768 conflicts were being reported as 0 by the shell, because 768 is a multiple of 256!

One of the things about rewriting an algorithm is that you have to understand whether a difference in behavior represents a bug in your new code (which is the vastly more likely case), or is actually a discovery of a bug that existed in the prior implementation, but was hitherto unknown.

Big kudos for the libgit2 team for working their way through this one!

No comments:

Post a Comment