Comment 6 for bug 277537

Revision history for this message
John A Meinel (jameinel) wrote :

So, I'm not sure why (B, C) matters so much versus (C, B). My best guess is that it has to do with null merges. I haven't looked at the specific texts, but my guess is that C somehow attributes everything to itself, because it had a cherry-pick or a null-merge done. Other than that, the order matters simply because we match one side first, and then only check for lines that did not match in the other parent.

I'm still not 100% sure why it matters, I'll try to get direct annotations and look at it. The annotation code is pretty straightforward, it does:

1) Get annotated lines for all parents
2) Compare the current un-annotated lines with the unannotated lines of the first parent.
   a) Wherever they match, take the annotation value from that parent
   b) Wherever they do not match, mark this as new in current revision
3) Compare the now annotated lines of this versus the annotated lines for the next parent.
  a) Wherever they match, just add them to the final result.
  b) For the annotated lines that do not match, match the unannotated lines against the unannotated lines for this parent.
     i. If the unannotated lines do not match, we keep the annotation as already generated
     ii. For lines which match, and the annotation says "current", we give them the annotation from the new parent
     iii. If the line already has a modified value, and it also matches the new parent, we do a heads() check to see if one revision_id supersedes the current revision_id. (For example, somebody modified a line, but then later modified it back, it will be annotated with the reverted revision)
        x) If one side clearly supersedes, use it
        y) If neither is an ancestor of the other, just pick one and use it

(y) was introduced because of your earlier concerns

For your other questions (in reverse order)

(4) push and pull won't propagate the changes, because they are only occurring in the deep ancestry (revisions which both sides already claim to have.) which effects 1. You can do the fix in any copy of the repository you want, but you need to find a way to get those changes to the other side.

The easiest ways are:
  a) Run reconcile directly in that repository
  b) Move the repository out of the way, and create a new empty one and do the fetch.

(3) It isn't strictly blocking, but I'm not 100% sure what happens if you add new revisions while doing reconcile. Ideally the new revisions would just get added on the side, and only the old revisions would get updated into the new pack file. I *think* that works, but I haven't specifically tested it.

(2) It is a bit slow, though I'm looking into it. ATM it isn't a 30s operation that is trivial to do on every repository. Which is why I suggested having something which could write out what had been modified, which could then be trivially applied to other repositories.

(1) As mentioned, it would generally be run on all repositories. Or you could run it locally, and then copy that to the central location.

I think reconcile should be run anyway, as it is better to have correct data stored. However, I can try and look to see if there is any obvious reason why the order of parents matters as much as it does. Looking at the algorithm, any lines which we do not agree on are resolved with an algorithm that does not care which came first.