I finally had a bit of time to follow this through. After running your set-up using revision.c and Makefile to emulate the situation, you can try running:
$ git diff-tree -B -C --numstat --summary HEAD
or
$ git diff-tree -B -M --numstat --summary HEAD
which would say:
90028d007986de4db8c3af30a2d5e5c00e5a2c8b
0 0 revision.c => old-revision.c
1117 1579 revision.c
rename revision.c => old-revision.c (100%)
rewrite revision.c (98%)The code is working as intended (it is a different discussion if "as intended" is actually the desired behaviour).
We take the preimage tree as a whole, and express postimage in terms of series of patches, _however_ we do not interpret the series of patches as _incremental_. IOW, when we talk about the effect of the second patch that describes the postimage of revision.c, we pretend as if nothing happened with the first patch (which renamed away revision.c). So "rewrite revision.c" is what we say, not "create revision.c anew, because the first one renamed it away".
This behaviour actually was a bit counterintuitive to me. I did not implement the very original rename/copy the way we currently operate. It was corrected into the current behaviour, following the guiding principle described in this message:
http://thread.gmane.org/gmane.comp.version-control.git/3807
which is reproduced below.
From: Linus Torvalds <torvalds@osdl.org>
Date: Mon, 23 May 2005 07:49:01 -0700 (PDT)
Subject: Re: [PATCH] Make sure diff-helper can tell rename/copy in the new
diff-raw format.
Message-ID: <Pine.LNX.4.58.0505230736180.2307@ppc970.osdl.org>
On Mon, 23 May 2005, Junio C Hamano wrote:
>
> This adds tests to make sure that diff-helper can tell renames
> from copies using the same "everything but the last one are
> copies and the last one is either rename or stay" logic. Btw, I still disagree...
...
For example, let's say that you have modified "fileA" _and_ you have
created a "fileB" that is a copy of the original "fileA" with some _other_
slight modifications. We'll call the SHA1's involved "sha_A", "sha_A'" and
"sha_B" I think it's perfectly valid to say
:100644 100644 <sha_A> <sha_A'> M fileA fileA
:100644 100644 <sha_A> <sha_B> C89 fileA fileB which says "fileA" was modified from orig-A to new-A, and "fileB" is a
copy based on orig-A. Now, when the above is turned into a "diff", that diff is no longer
something you can apply "incrementally" - you have to apply it as if
you're applying all differences to the "original tree". But the thing is,
that's actually what I _want_, because I was planning on writing a tool
that applies patches that applies them all-or-nothing. Also, it turns out that this kind of "non-incremental" diff is the kind
that I personally want to see as a _human_, because quite frankly, my
brain-capacity is that of a demented ocelot, and I can't _remember_ what
happened in other parts of the diff. I much prefer the stateless "oh, this
file X is in that relation Y to the previous version of file Z". I do that partly because I actually routinely edit patches. If you have
the incremental format, that's practically impossible, while the stateless
version is fine. See?
So I think all the clever "don't re-use files we have modified" etc is
actually wrong. If you want to make a traditional diff that can be applied
with normal "patch", you just don't use the -M or -C flags. Linus