= mergediff = ''Author'': wolever Repository: https://bitbucket.org/wolever/hg-mergediff/ (work in progress - see [[#Status|status]]) Show only the changes introduced by a merge. Use case: you are reviewing code, and you would like to see only the changes that were introduced by a merge, but *not* the changes leading up to the merge. {{{#!wiki caution This extension does not currently work with Mercurial >=1.9 }}} = Example = {{{ $ hg mdiff --- a/changed_in_merge # changed to "in a" in branch 'a' --- b/changed_in_merge # changed to "in b" in branch 'b' +++ c/changed_in_merge # changed to "merged" in the merge - in b -in a ++merged --- a/resolved # same as above, except changed to "in a" +++ c/resolved # to resolve the merge conflict - in b + in a --- /dev/null --- /dev/null +++ c/added_in_merge # file added in the merge ++added in merge }}} = Algorithm = Imagine a DAG that looks like this (arrows point from child to parent): {{http://img.skitch.com/20100224-ruq9ipk5mnd23f88a82b16ng24.png}} Note that: * `AP1`, `AP2`, `P1M` and `P2M` are sets of diff hunks * Hunks in `AP1` and `AP2` should //not// be included in the merge diff * `P1M` contains `AP2` and `P2M` contains `AP1` (ie, `AP2` ⊆ `P1M` and `AP1` ⊆ `P2M`) Therefore, the merge diff should contain exactly: `AP2`-`P1M` ∪ `AP1`-`P2M` (where "-" is the "set difference" operation). = Status = The mergediff algorithm has been implemented and appears to function correctly. The implementation is currently suboptimal (it uses more time and memory than is strictly necessary)… But this should only be a problem for "really big" merges. = Caveats = The algorithm which compares hunks (ie, to perform `AP2`-`P1M`) only considers the source file, destination file and context diff. Notably, it does //not// consider the diff's location in the destination file. I've done this to help cope with situations where, for example, changes are made above a hunk in one branch, which causes their offset to be different in the "parent to merge" diff than it is in the "base to parent" diff. Here's an example, from the [[#Code|testing repository]]: {{{ $ hg diff -r a:merge diff --git a/top_bottom b/top_bottom --- a/top_bottom +++ b/top_bottom @@ -10,3 +10,4 @@ <<< note: line 10 unchanged line 7 unchanged line 8 unchanged line 9 +bottom change $ hg diff -r 0:b diff --git a/top_bottom b/top_bottom --- a/top_bottom +++ b/top_bottom @@ -9,3 +9,4 @@ <<< note: line 9 unchanged line 7 unchanged line 8 unchanged line 9 +bottom change }}} This could potentially lead to changes being incorrectly ignored (eg, if a change which should not be ignored has the same context diff as a change which should be ignored)… But I'm not sure what the best way to fix it will be. = Code = The code is available at: http://bitbucket.org/wolever/hg-mergediff/ I've tried to roughly emulate [[http://www.kernel.org/pub/software/scm/git/docs/git-diff.html#_combined_diff_format|git's combined diff format]]. There are, however, some notable differences: = Format notes = * mdiff may include three files in the header, instead of only two * mdiff does not include any extended headers * mdiff only includes the target file's range (this is only because I'm lazy - it should technically be possible to implement) = FAQ = '''Q: What's wrong with `hg diff -r `?''' <
> A: In short, `diff -r ` will show changes from one of the branches. For example, taking the `diff` of a clean merge will show changes, but showing the `mergediff` of a clean merge will not. '''Q: Isn't this the same as `git`'s combined diff?'''<
> A: No. Among other things, `git`'s combined diff doesn't show new changes (ie, changes that weren't conflict resolutions) and it only shows resolutions to one of the merge parents. For more examples, compare the output of `hg mergediff -r merge` to the output of `git diff merge^` in the repository created by [[http://bitbucket.org/wolever/hg-mergediff/src/tip/mktestrepo|mktestrepo]]. ---- CategoryExtensionsByOthers