diff -r 282b288aa20c -r 4d504e541d3d mercurial/merge.py --- a/mercurial/merge.py Tue May 02 23:47:10 2017 -0700 +++ b/mercurial/merge.py Wed May 03 10:43:59 2017 -0700 @@ -786,7 +786,7 @@ return True def manifestmerge(repo, wctx, p2, pa, branchmerge, force, matcher, - acceptremote, followcopies): + acceptremote, followcopies, forcefulldiff=False): """ Merge wctx and p2 with ancestor pa and generate merge action list @@ -821,6 +821,26 @@ if any(wctx.sub(s).dirty() for s in wctx.substate): m1['.hgsubstate'] = modifiednodeid + # Don't use m2-vs-ma optimization if: + # - ma is the same as m1 or m2, which we're just going to diff again later + # - The matcher is set already, so we can't override it + # - The caller specifically asks for a full diff, which is useful during bid + # merge. + if (pa not in ([wctx, p2] + wctx.parents()) and + matcher is None and not forcefulldiff): + # Identify which files are relevant to the merge, so we can limit the + # total m1-vs-m2 diff to just those files. This has significant + # performance benefits in large repositories. + relevantfiles = set(ma.diff(m2).keys()) + + # For copied and moved files, we need to add the source file too. + for copykey, copyvalue in copy.iteritems(): + if copyvalue in relevantfiles: + relevantfiles.add(copykey) + for movedirkey in movewithdir.iterkeys(): + relevantfiles.add(movedirkey) + matcher = scmutil.matchfiles(repo, relevantfiles) + diff = m1.diff(m2, match=matcher) if matcher is None: @@ -974,7 +994,7 @@ repo.ui.note(_('\ncalculating bids for ancestor %s\n') % ancestor) actions, diverge1, renamedelete1 = manifestmerge( repo, wctx, mctx, ancestor, branchmerge, force, matcher, - acceptremote, followcopies) + acceptremote, followcopies, forcefulldiff=True) _checkunknownfiles(repo, wctx, mctx, force, actions, mergeforce) # Track the shortest set of warning on the theory that bid