We have been deployed fully and using mercurial/kiln for about 1 month now in our team of about 30 engineers, having transitioned from an older centralized version control system.
A couple of times, the "hg merge" has selected what we think is the "wrong" change. I have been able to reproduce a recent incident where hg merge reported no conflicts but we believe selected the wrong change, and we are confused and do not understand the logic.
I was trying to find the actual "algorithm" used by mercurial during its merge, but google was not my friend on this.
Anyhow, does anyone know how mercurial selects changes during the automatic hg merge?
Mercurial first finds the most recent common ancestor between the two changesets (let's call them A and B) you are merging. This is considered the base.
Any files that have not been modified since the base are not in conflict.
If a file has been modified only in A or B's development line, then that modification is taken, and is not in conflict.
If a file has been modified in A and renamed in B (or vice-versa), then B's rename is adopted with A's changes, and is not a conflict.
If a file is renamed in both A and B, deleted in one but modified in the other, or some other variant of those, Mercurial notes it as a tree conflict, and you must manually resolve.
If a file has been modified on both A and B, Mercurial finds a merge strategy based on the content of the file. If your file is anything but ASCII or Unicode text, Mercurial will probably note the file as conflicted. Assuming the file is text:
Mercurial will first attempt to perform an internal three-way merge. The general idea is that if the changes in A and B from the LCA do not overlap, then they are considered non-conflicting, and can be adopted.
If there are conflicting ranges, Mercurial instead hands off the merge to the three-way merge tool you have requested. For TortoiseHg, that default is kdiff3. kdiff3 is frequently able to merge files successfully that Mercurial's internal merge tool cannot. If kdiff3 believes it has successfully merged, then it will tell Mercurial so, and will record that as a successful merge.
Further, if you have conflict in kdiff3, but you resolve them yourself and save your changes, then that also will be counted as a successful merge, and not show up as an unresolved conflict.
A failure status code from the 3-way merge tool, or the absence of one, will leave the file in a conflicted state.
If you would like to contact us privately to talk about the specific instance you hit, or if you can provide an example of what you think is erroneous on a dummy repository, I can probably help you figure out why Mercurial is merging the way it is.