If the -M flag and an explicit revision range is given to hg log, the order can be reversed compared to what is expected. Reported to the mailing list http://www.selenic.com/pipermail/mercurial/2014-June/047249.html Example: (taken from Matt Mackall's reply to the list) Observed: $ hg log -M -q -r 10:9 9:b4d0c3786ad3 10:e76ed1e480ef Expected: $ hg log -M -q -r 10:9 10:e76ed1e480ef 9:b4d0c3786ad3 Further information: # Correct on version 2.9 (i.e. this is a regression from previous) $ hg29 log -q -M -r 10:9 10:e76ed1e480ef 9:b4d0c3786ad3 # Correct on current version without -M $ hg log -q -r 10:9 10:e76ed1e480ef 9:b4d0c3786ad3 # Correct on current version with a revset $ hg log -M -q -r "(10:9)" 10:e76ed1e480ef 9:b4d0c3786ad3 # Correct on current version with -M in revset $ hg log -q -r 'not merge() and 10:9' 10:e76ed1e480ef 9:b4d0c3786ad3 Work around: Use a revset, i.e. $ hg log -M -q -r "(10:9)"
I have submitted a patch to the dev mailing list.
Thanks for the swift response. I downloaded a tip snapshot (at rev 61b333b982ea) and I applied your patch 'by hand' to cmdutil.py. I don't believe this fixes the problem completely. # Without -M $ hg log -q -r 1:0 1:6b37d498935b 0:1a6eb00afbdc $ hg log -q -r 0:1 0:1a6eb00afbdc 1:6b37d498935b # With -M $ hg log -M -q -r 1:0 1:6b37d498935b 0:1a6eb00afbdc $ hg log -M -q -r 0:1 1:6b37d498935b 0:1a6eb00afbdc The last one is now wrong (or at least doesn't match the case without -M) Also now even with a revset it is wrong: $ hg log -M -q -r "(0:1)" 1:6b37d498935b 0:1a6eb00afbdc
I've been stepping through with a debugger, looking at the difference between -M and no -M, '-r 1:0' and '-r "(1:0)"' etc. (all based on 3.0.1) Specifically looking at cmdutil.getlogrevs() I see that scmutil.revrange() returns a mercurial.revset.orderedlazyset for '-r "(1:0)"' and a mercurial.revset.baseset for '-r 1:0' Then _makelogrevset is used to get 'expr' which is None for no -M and and a filter (not merge()) for -M. The 'not' filter works by using the __sub__ operator of the revision set, and for a mercurial.revset.baseset (I think) this can alter the order of elements (fair enough since sets aren't supposed to be ordered). For a mercurial.revset.orderedlazyset the order is maintained. So I think maybe if scmutil.revrange() always returned an ordered set this might work, however there are quite a few lines in cmdutil.getlogrevs() devoted to re-ordering the sets and I don't quite understand them all. Hope that helps?
That really did help :) I have sent another patch to the dev mailing list which I hope has fixed the issue. Added a test case too. Please let me know your thoughts on the same. Instead of using an orderedlazyset I have removed just the merged-rev entry from the list of rev ranges.
Fixed by http://selenic.com/repo/hg/rev/dd716807fd23 Matt Mackall <mpm@selenic.com> revset: maintain ordering when subtracting from a baseset (issue4289) (please test the fix)
This works for me. Thank you for your help.