Fix: Broken round-trip fidelity for merges of converged files#207
Conversation
Currently fails.
…ne parent. First one currently fails.
|
Thanks, pushed. Outstanding detective work! On Tue, May 24, 2011 at 1:49 PM, cwalther
|
|
Thanks, that was quick! |
I have found a circumstance in which pushing a changeset from Mercurial to Git, then pulling it back again will result in a different changeset ID (as well as slight repository corruption that will break some operations such as copy detection).
This happens when the changeset in question is a merge that contains files that had the same contents in both parents, but arrived at those contents by different histories (and therefore have different file revisions in Mercurial). When making such a merge, Mercurial will create a new file revision that ties together the two parent revisions, and therefore reports the file as changed in the merge, even though its content did not change with respect to either parent. Git on the other hand only tracks file contents, not their histories, and will therefore not report the file as changed after importing that merge into Git. On pulling back the merge into Mercurial, Hg-Git must recreate the merged file revision, even though it is not told so by Git. It currently does not do that, but keeps the file revision from the first parent, with the result that 1. the changeset ID is different from the original, and 2. the filelog history is disjoint and doesn’t match the changeset history, so that activities that travel back along the file history, e.g. copy detection while merging, will fail when trying to go back to an ancestor that lies in the history of the second parent.
The same thing also happens when a merge conflict is resolved by taking the entire file contents from the first parent and discarding any changes from the second parent.
The following shell script will reproduce the issue, showing that the original and back-imported revision IDs are different, and why:
The attached commits add a test for the problem (that currently fails) and a fix (that makes the test succeed and doesn’t break any other tests that weren’t failing already).