diff mercurial/simplemerge.py @ 28072:c3e9269d9602

merge: minimize conflicts when common base is not shown (issue4447) Previously, two changes that were nearly, but not quite, identical would result in large merge conflict regions that looked very similar, and were thus very confusing to users, and lead people used to other source control systems to claim that "mercurial's merge algorithms suck". In the relatively common case of a new file being introduced in two branches with very slight modifications, the old behavior would show the entire file as a conflict, and it would be very difficult for a user to determine what was going on. In the past, mercurial attempted to solve this with a "very smart" algorithm that would find all common lines, but this has significant problems as described in 2ea6d906cf9b. Instead, we use a "very dumb" algorithm introduced in the previous patch that simply matches lines at the periphery of conflict regions. This minimizes most conflict regions well, though there may still be some degenerate edge cases, like small modification to the beginning and end of a large file.
author Ryan McElroy <rmcelroy@fb.com>
date Wed, 10 Feb 2016 09:06:08 -0800
parents 261324dd5f5b
children 5f7d13d3bd4d
line wrap: on
line diff
--- a/mercurial/simplemerge.py	Wed Feb 10 08:25:03 2016 -0800
+++ b/mercurial/simplemerge.py	Wed Feb 10 09:06:08 2016 -0800
@@ -92,7 +92,8 @@
                     mid_marker='=======',
                     end_marker='>>>>>>>',
                     base_marker=None,
-                    localorother=None):
+                    localorother=None,
+                    minimize=False):
         """Return merge in cvs-like form.
         """
         self.conflicts = False
@@ -109,6 +110,8 @@
         if name_base and base_marker:
             base_marker = base_marker + ' ' + name_base
         merge_regions = self.merge_regions()
+        if minimize:
+            merge_regions = self.minimize(merge_regions)
         for t in merge_regions:
             what = t[0]
             if what == 'unchanged':
@@ -441,7 +444,10 @@
         out = sys.stdout
 
     m3 = Merge3Text(basetext, localtext, othertext)
-    extrakwargs = {"localorother": opts.get("localorother", None)}
+    extrakwargs = {
+            "localorother": opts.get("localorother", None),
+            'minimize': True,
+        }
     if mode == 'union':
         extrakwargs['start_marker'] = None
         extrakwargs['mid_marker'] = None
@@ -449,6 +455,7 @@
     elif name_base is not None:
         extrakwargs['base_marker'] = '|||||||'
         extrakwargs['name_base'] = name_base
+        extrakwargs['minimize'] = False
     for line in m3.merge_lines(name_a=name_a, name_b=name_b, **extrakwargs):
         out.write(line)