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

Bug in "git blame -C"

From
Linus Torvalds <torvalds@osdl.org>
Date
Nov 29, 2006, 04:27 UTC
Message-ID
<Pine.LNX.4.64.0611282013430.3395@woody.osdl.org>
Ok, this is interesting.

Try this sequence (which is a good sequence for showign how something like "git blame -C" _should_ work, but only ends up showing that it doesn't at all, because of some bug ;^):

	#
	# create 'testing' repository
	#
	mkdir testing
	cd testing/
	git init-db
	#
	# copy git.c and sha1_file.c there and commit initial
	# (Just to get _some_ initial state)
	#
	cp ~/git/git.c .
	cp ~/git/sha1_file.c .
	git add git.c sha1_file.c
	git commit -m Initial
	#
	# move the prepend_to_path() function from git.c to
	# sha1_file.c (I did it to just after the
	#	#ifndef O_NOATIME
	# block of preprocessor stuff
	#
	em git.c sha1_file.c
	git commit -a -m Movement
	git log -p
and the result of that "git log -p" should show something like
	commit a583b5aee68b89b7d554b8f900a95057e8ed61d9
	Author: Linus Torvalds <torvalds@woody.osdl.org>
	Date:   Tue Nov 28 20:13:00 2006 -0800
	
	    Movement
	
	diff --git a/git.c b/git.c
	index 357330e..43c01fd 100644
	--- a/git.c
	+++ b/git.c
	@@ -18,28 +18,6 @@
	 const char git_usage_string[] =
	        "git [--version] [--exec-path[=GIT_EXEC_PATH]] [-p|--paginate] [--bare] [--git-dir=GIT_DIR] [--help] COMMAND [AR
	
	-static void prepend_to_path(const char *dir, int len)
	-{
	-       const char *old_path = getenv("PATH");
	-       char *path;
	-       int path_len = len;
	...
	diff --git a/sha1_file.c b/sha1_file.c
	index 63f416b..20168aa 100644
	--- a/sha1_file.c
	+++ b/sha1_file.c
	@@ -22,6 +22,28 @@
	 #endif
	 #endif
	
	+static void prepend_to_path(const char *dir, int len)
	+{
	+       const char *old_path = getenv("PATH");
	+       char *path;
	+       int path_len = len;
	+
	...

to show how that top commit moved the function. Ok, everything looks fine so far.

For the surreal behaviour, now do
	git blame -C sha1_file.c

and watch the result make no sense what-so-ever. It doesn't show the movement at all. It shows that everything in that file came from the original commit, even though the file obviously did change since.

Which is kind of "true", but it's still _wrong_. Yes, all the data comes from the same (initial) commit, but it doesn't come from the same _files_ in the same commit, so the fact that we don't see the filenames and original lines in those filenames is _broken_. The commit information is right, but it's decided not to show all the _other_ information that is crucial..

So this shows two problems:
 - the line numbers that "git blame -C" shows are the current line numbers 
   only, not the line numbers it came from in the version it shows. That 
   makes them useless. We _know_ the current linenumbers. What we want to 
   know is what they were in the commit that they came from.
   So right now, the line number information that "git blame -C" shows is 
   just the same thing we could have gotten by doing a "cat -n file".
 - "git blame -C" has apparently decided that it doesn't need to show 
   filenames that things came from, because they all came from the same 
   commit, but that's not a logical thing to compare. "same commit" does 
   not mean "same filename", so not showing the filename makes no sense.

I tried to bisect this a bit, but I don't think pickaxe has ever gotten this right, so I couldn't find a place where it was correct to start bisecting at ;)

Next: Junio C Hamano
Message 1 of 4 in “Bug in "git blame -C"”
  1. Linus TorvaldsNov 29, 2006
  2. Junio C HamanoNov 29, 2006
  3. Junio C HamanoNov 29, 2006
  4. git blame -C: fix output format tweaks when crossing file boundary.Junio C Hamano, Nov 29, 2006

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.