sageserpent-open / kineticMerge

Merge a heavily refactored codebase and stay sane.
MIT License
9 stars 1 forks source link

When do merge conflicts end? #27

Closed sageserpent-open closed 4 months ago

sageserpent-open commented 4 months ago

It is likely that the implementation of #13 will tie into the handling of merge conflicts, either directly in the merge algorithm or as a post-processing step. This is because several of the code motion merge cases involve what look like conflicts in isolation, but are actually the changes at the source site for a move section with an associated edit or deletion.

Analysing these cases is fairly straightforward when the moved section is cleanly edited into another section, or is deleted outright, on the side opposite to the move. Where it gets messier is when multiple sections are involved on the opposite side.

At first glance this seems irrelevant for the section-based merge, because an unmatched section would not be accompanied by another unmatched section, rather they would be merged into one larger section by CodeMotionAnalysis. The twist is that another unrelated moved section may land right in the middle of the merge conflict site on the side opposite to the move - this will by virtue of being a matched section have to stand alone, so it could be accompanied on either side by unmatched sections or by still another moved section.

This leads to corner cases where if an unrelated moved section B lands on the opposite side to the site of a moved section A's source, then it can signify the deletion of A, or if it is accompanied by a single unmatched section C, then C is propagated as an edit of A to its destination location. If B is flanked by two unmatched sections, then there is an ambiguity as to which one could be considered to be the edit of A and an edit collision must be raised.

This generalises to when multiple unrelated moved sections land on the opposite side - as long as there are no flanking / interspersed unmatched sections (ie. a deletion to propagate) or just a single flanking or interspersed unmatched sections (ie. an edit to propagate), then we may consider multiple moved sections as legitimate insertions.

So this would favour rolling up insertions on each side of a merge conflict to make chunky conflicts, allowing easier analysis by the code motion postprocessing step.

sageserpent-open commented 4 months ago

This leads to another thought - if we treat unrelated moved sections as being allowed to land in the middle of the source of a moved section (because we consider the matching of text across locations as making them special in their own right), then what happens at the other end when a moved section lands in the middle of a plain edit as the editing section?

Presumably it's OK to treat it as an edit, because even if we don't and just insert it, then the edit degenerates into a deletion which when combined with the insertion leads right back to being an edit!

sageserpent-open commented 4 months ago

Added new tests to prove that merge conflicts are made chunky when possible, these pass in Git commit SHA: 5c6e214bad2798a99a3a3ba5e87c43007c1ba1c5.

Should the results of the merge stay as is - this flattens the conflicts into a left and a right version of the final file, or should the results allow the conflicts to be analysed one by one?

sageserpent-open commented 4 months ago

This went out in release 0.2.6, Git commit SHA: b8c72aef97396001441dacbd8e3ed8479a6dc80e.

sageserpent-open commented 4 months ago

What happens now is that there is a merge algebra that allows different client codebases to build their own flavour of merge result. The merge algebra API allows edits, insertions, deletions, preservations and conflicts to be registered by merge.of as it works its way through the merge.

Edits are kept separate from the point of view of the edited elements in the base, but coalesce with following insertions of the same kind - so left edits grab left insertions, right edits grab right insertions and coincident edits grab coincident insertions.

Conflicts will grab insertions that are not already claimed by edits, and will do so even if the insertions could be considered as non-conflicting in isolation - the effect is that a conflict plays no favourites between the elements on either side of a conflict.

Conflicts also merge their base elements, in contrast with edits.