git/list[1] front-page[2] threads[3] people[4] search[5] about
 

Re: bisect / history preserving on rename + update

From
Linus Torvalds <torvalds@linux-foundation.org>
Date
Aug 25, 2007, 15:38 UTC
Message-ID
<alpine.LFD.0.999.0708250819360.25853@woody.linux-foundation.org>
In-Reply-To
<7vmywgb45c.fsf@gitster.siamese.dyndns.org>
On Fri, 24 Aug 2007, Junio C Hamano wrote:
Show 18 quoted lines
> 
> 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%)
Yeah, in that format, git behaviour actually looks really nice.
> The code is working as intended (it is a different discussion if
> "as intended" is actually the desired behaviour).
I think it may be at times.
> 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_.

IIRC, that's not strictly true. We do have logic to make sure that the difference between "copy" and "rename" is that the rename happens only once, ie I just tested this sequence:

	mkdir test-rename
	cd test-rename/
	cp /home/torvalds/git/revision.c .
	git init
	git add .
	git commit -m "add revision.c"
	cp revision.c rev1.c
	cp revision.c rev2.c
	rm revision.c
	em rev1.c
	em rev2.c
	git add .
	git commit -a -m "rename revision.c twice"

(the two "em" calls are just me in an editor, adding a line to the top of the file saying "This is rev[12].c")

After that, doing a "git show -C" shows:
	diff --git a/revision.c b/rev1.c
	similarity index 99%
	copy from revision.c
	copy to rev1.c
	...
	diff --git a/revision.c b/rev2.c
	similarity index 99%
	rename from revision.c
	rename to rev2.c
	...

so we do have a notion of "incremental" in that the first is a copy, the second is a rename, and that the rename is expected to remove the file.

(Doing a "--stat" doesn't show the difference between copy and rename, so we'll just see it as

	 revision.c => rev1.c |    1 +
	 revision.c => rev2.c |    1 +
which looks pretty).
Show 5 quoted lines
> 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".
If that was consistent, then we'd have used "rename" in both cases above..
> 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
Ahh, you're a wily one. Using my own words against me.

But that earlier Linus was obviously a fake impostor, since he was wrong (and could thus by definition not _possibly_ be the true Linus!). So your judo mindtrick fails.

That said, I actually think that the earlier Linus might actually be me, and he's right in the case he mentions: we should *not* break the association if it results in a good diff!

Ie, the true "guiding principle" should be the principle of minizing the final diff - that's how diff is supposed to act within a single file, and I think it's how the rename/copy detection is supposed to act too.

So:
Show 7 quoted lines
>     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.

This is 100% consistent with "how do I minimally show the differences between the original and the result": we decide that we can show it as a "copy" and a "modification" of the original file.

But it makes sense to "copy and modify the original", but it does *not* make sense to "rename and modify the original". That is, after all, the *only* difference between copying and renaming. A copy will leave the original around (so that it can be modified), while a rename will not.

So, by the very definition of "rename", doing a "rename and modify the original" would appear to be somewhat senseless, no?

			Linus
Previous: David KastrupNext: Junio C Hamano
Message 14 of 15 in “bisect / history preserving on rename + update”
  1. Thomas GleixnerAug 14, 2007
  2. Karl HasselströmAug 14, 2007
  3. Thomas GleixnerAug 14, 2007
  4. Karl HasselströmAug 14, 2007
  5. Thomas GleixnerAug 14, 2007
  6. David KastrupAug 14, 2007
  7. Karl HasselströmAug 14, 2007
  8. Thomas GleixnerAug 14, 2007
  9. David KastrupAug 14, 2007
  10. David KastrupAug 14, 2007
  11. Linus TorvaldsAug 14, 2007
  12. Junio C HamanoAug 25, 2007
  13. David KastrupAug 25, 2007
  14. Linus TorvaldsAug 25, 2007
  15. Junio C HamanoAug 25, 2007

Read the whole thread, see it on lore, or plain text.

$ cat FOOTERMessages come from the public archive at lore.kernel.org/git, fetched every hour. The front page is chosen and written each morning by an AI editor and can be wrong; the threads themselves are the record. About and API. For agents: an MCP server at https://gitlist.dev/mcp, and any thread, story or person page as Markdown by adding .md to its URL (or sending Accept: text/markdown). Details in /llms.txt.