Hi folks, while trying to parse git diff-tree output, I found out that in some cases it appears to generate an incorrect diff (AFAICT). I orginally found this in a 5-way merge commit in the Linux kernel, but managed to reduce this to something a lot more managable (an ordinary 2-way merge on a 6-line file). To start with the wrong-ness, this is the diff generated: $ git diff-tree -p -c HEAD d945a51b6ca22e6e8e550c53980d026f11b05158 diff --combined file index 3404f54,0eab113..e8c8c18 --- a/file +++ b/file @@@ -1,7 -1,5 +1,6 @@@ +LEFT BASE2 BASE3 BASE4 - BASE5 + BASE5MODIFIED BASE6 Here, the header claims that the first head has 7 lines, but there really are only 6 (5 lines of context and one delete line). The numbers for the others heads are incorrect. In the original diff, the difference was bigger (first head was stated to have 28 lines, while the output was similar to the above). To find out what's going on, we can look at the -m output, which is correct (or look at the original file contents at the end of this mail). $ git diff-tree -m -p HEAD d945a51b6ca22e6e8e550c53980d026f11b05158 diff --git a/file b/file index 3404f54..e8c8c18 100644 --- a/file +++ b/file @@ -1,7 +1,6 @@ LEFT -BASE1 BASE2 BASE3 BASE4 -BASE5 +BASE5MODIFIED BASE6 d945a51b6ca22e6e8e550c53980d026f11b05158 diff --git a/file b/file index 0eab113..e8c8c18 100644 --- a/file +++ b/file @@ -1,3 +1,4 @@ +LEFT BASE2 BASE3 BASE4 As you can see here, first head added "LEFT", and the second head removed "BASE1" and modified "BASE5". In the -c diff-tree output above, this removal of "BASE1" is not shown, but it is counted in the number of lines, causing this breakage. Note that to trigger this behaviour, the number of context lines between the BASE1 and BASE5 must be _exactly_ 3, more or less prevents this bug from occuring. Also, the "LEFT" line introduced does not seem to be essential, but there needed to be some change from both sides in order to generate a diff at all. I haven't looked into the code, though I might give that a go later. Anyone got any clue why this is happening? Is this really a bug, or am I misunderstanding here? To recreate the above situation, you can use the following commands: git init cat > file <<EOF BASE1 BASE2 BASE3 BASE4 BASE5 BASE6 EOF git add file git commit -m BASE git checkout -b RIGHT cat > file <<EOF BASE2 BASE3 BASE4 BASE5MODIFIED BASE6 EOF git commit -m RIGHT file git checkout -b LEFT master cat > file <<EOF LEFT BASE1 BASE2 BASE3 BASE4 BASE5 BASE6 EOF git commit -m LEFT file git merge RIGHT cat > file <<EOF LEFT BASE2 BASE3 BASE4 BASE5MODIFIED BASE6 EOF git add file git commit --no-edit git diff-tree -p -c HEAD Gr. Matthijs -- To unsubscribe from this list: send the line "unsubscribe git" in the body of a message to majordomo@xxxxxxxxxxxxxxx More majordomo info at http://vger.kernel.org/majordomo-info.html