Open sageserpent-open opened 1 year ago
What are Git's merge's rules for precedence when merging with whitespace changes when an option to ignore whitespace is in force?
OURS | THEIRS | OUTCOME |
---|---|---|
Whitespace changes | Whitespace changes | Our whitespace changes |
Whitespace changes | Non-trivial changes | Their non-trivial changes |
Non-trivial changes | Whitespace changes | Our non-trivial changes |
No change | Whitespace changes | No change |
Whitespace changes | No change | Our whitespace changes |
No change | Non-trivial changes | Their non-trivial changes |
Non-trivial changes | No change | Our non-trivial changes |
Non-trivial changes | Non-trivial changes | Conflict |
This came up in #30 when reviewing the results of MainTest.anEditAndADeletionPropagatingThroughAFileSplit
- see anEditAndADeletionPropagatingThroughAFileSplit.
Need to review that in the context of the ticket. Speaking as a user, I would want to see the edit on the right in the tested merge make its way into the move destination contributed by the left, which isn't the case with the current dominance rule in the code (ca10050d36cbc7e956d287f6d905130d9decffa5).
Something to be mindful of - the example discussed in #30 is for a merge where our branch - the left is the one that has the condensation, their - the right branch has the whitespace edit.
This is the first test case executed by that test.
If the sense of merging is reversed, so the condensation is merged into the edits, then I'd expect a better looking result.
The behaviour we want in the last comment - namely to propagate the whitespace change on the right (theirs) to the move destination on the left (ours) goes against what Git specifies in the table above - well, assuming that table fairly summarizes what Git does.
Given the merge would look better with the desired behavour, let's go with it and not follow the table to the letter...
Scouting in the codebase, it seems that are at least two parts to this last piece of work, corresponding to two use-cases:
For the sake of centralising logic (and testing of that logic), I'm wondering whether to treat the first situation as being a kind of edit (because from the user's point of view, that's what it is) when just one side makes a whitespace edit wrt the base. If both or neither do, then it gets treated as a preservation. Then again, what about coincident edits? Do we do the same thing thing there? Or push it all down into the underlying merge algebra? Um, ah...
Musing ... consider using an abstract strategy to fuse the left and right contributions and pass this into the underlying merge algebra. Cutover MergeTest
so that it double checks that the resulting merge actually uses the strategy by re-using the strategy in its expectations - or switching from a left-bias to a right-bias in different trials. This allows preservations and coincident edits to be handled in the usual fashion.
The code up in the merge algebra for MatchesContext
needs to use the same strategy to build a edit to be migrated to the move destination when handling a deletion (specifically when one side has made a whitespace-only edit and the other has moved the section). The edit is the fusion of the move destination's section with the whitespace-edited section.
It would be nice to suppress any migrated whitespace-only edits when the fusion leads to the same result as the move destination. Could this be done with a simple equality check?
TODO: fix the logging message for preservations in merge.of
- it currently refers to the left side only, this needs to change given this ticket...
As of b5188269cb933218c85f8dbd73235f1bd49ecd86, got support for the simple edit case without code motion.
This is essentially duplicating what
git merge
can do with its various options:That are passed to its
ort
strategy. Before proceeding with this, it would be nice to know exactly where in Git's merge plumbing this stuff gets used and how it could be applied to Kinetic Merge.Given that code may move between files, just how sacred is the whitespace anyway? I'm not sure that duplicating exactly what Git does is the best option here.