threads / discuss / 26741

git blame --follow

Subject: git blame --follow

## tl;dr

6 messages between Mar 15, 2011 and Mar 17, 2011.

replies: 5people: 3as markdown or json

Wolfgang Rohdewald· Mar 15, 2011, 15:44 UTC · lore
git log --follow filename
shows the full history, while
git blame --follow filename

blames everything to the latest commit (which was a file rename)

it would be nice if --follow were also supported by git blame. Actually git blame accepts --follow without an error message, it just ignores it. git help blame does not mention --follow

using latest git from master git version 1.7.4.1.234.ga3513

-- 
Wolfgang
Junio C Hamano· Mar 15, 2011, 17:30 UTC · re: Wolfgang Rohdewald · lore

Re: git blame --follow

Wolfgang Rohdewald <wolfgang@rohdewald.de> writes:
Show 8 quoted lines
> git log --follow filename
>
> shows the full history, while
>
> git blame --follow filename
>
> blames everything to the latest commit (which was
> a file rename)
Huh?
    $ git checkout master^0
    $ git mv COPYING RENAMING
    $ git commit -m renamed
    $ git blame --follow RENAMING

gives everything blamed to 075b845a COPYING (but that is probably by accident, see below). FYI,

    $ git blame RENAMING

should also blame everything to the same commit and the same COPYING file. If you get a different behaviour out of the above command sequence, there is something else going on.

I didn't know "blame" even accepted "--follow". It is entirely out of the scope of its design to take "--follow" option, as the "blame" command itself has its own and real "follow" logic that is enabled by default (i.e. it follows a whole file rename without any option), instead of the checkbox "--follow" hack that is in "git log" family of commands. You cannot even turn it off.

Perhaps the behaviour you saw comes from the internal revision traversal machinery blame uses getting confused by the use of --follow, but I am too lazy to check (and I don't think it is worth to check, as the command should follow by default).

We should just teach "blame" to ignore --follow option from the command line, without even complaining.

Wolfgang Rohdewald· Mar 15, 2011, 18:26 UTC · re: Junio C Hamano · lore

Re: git blame --follow

On Dienstag 15 März 2011, Junio C Hamano wrote:
Show 25 quoted lines
> Wolfgang Rohdewald <wolfgang@rohdewald.de> writes:
> > git log --follow filename
> > 
> > shows the full history, while
> > 
> > git blame --follow filename
> > 
> > blames everything to the latest commit (which was
> > a file rename)
> 
> Huh?
> 
>     $ git checkout master^0
>     $ git mv COPYING RENAMING
>     $ git commit -m renamed
>     $ git blame --follow RENAMING
> 
> gives everything blamed to 075b845a COPYING (but that is
> probably by accident, see below).  FYI,
> 
>     $ git blame RENAMING
> 
> should also blame everything to the same commit and the same
> COPYING file. If you get a different behaviour out of the
> above command sequence, there is something else going on.

I get the same - except that only most is attributed to 075b845a, some is attributed to 703601d6. But git blame and git blame --follow return the same output with your example

Show 5 quoted lines
> I didn't know "blame" even accepted "--follow".  It is
> entirely out of the scope of its design to take "--follow"
> option, as the "blame" command itself has its own and real
> "follow" logic that is enabled by default (i.e. it follows a
> whole file rename without any option)

so if I rename a parent directory of myfile and do git blame myfile, blaming should ignore the renaming. This works with the git repo

git mv xdiff xxx git ci -m'mv xdiff xxx' cd xxx git blame xemit.c

But with my repository (which I cannot share), this does not happen. git blame attributes everything to the renaming commit. If I checkout the commit before, git blame shows everything correctly.

So there must be something special with my repo. How could I debug that? BTW the renaming happened in svn, it is the last svn commit for this file before I imported this svn repo into git (like described in the Pro Git book)

And - for directories below the renamed one git log --follow cannot cross this barrier either but if the "follow" logic is different I suppose this is not related

-- 
Wolfgang
Jakub Narebski· Mar 17, 2011, 09:59 UTC · re: Wolfgang Rohdewald · lore

Re: git blame --follow

Wolfgang Rohdewald <wolfgang@rohdewald.de> writes:
> But with my repository (which I cannot share),
> this does not happen. git blame attributes everything to 
> the renaming commit. If I checkout the commit before, git
> blame shows everything correctly.
"git blame" manpage says:
       -M|<num>|
              Detect  moved  or copied lines within a file. [...]
              [...]
              <num> is optional [...]
       -C|<num>|
              In  addition  to  -M,  detect lines moved or copied from other files
              that were modified in the same commit.
Sidenote: I wonder why we use '-M|<num>|' and not '-M[<num>]' here.

So you probably want to run "git blame -C -C <file>", not "git blame <file>". Note that it is the same option name to turn on rename detection as is used for for "git diff".

Note that "git gui blame" shows _two_ commits for each line: one is result of "git blame" (and it would show commit that did code movement, or renamed file), the other is result of "git blame -C -C -w", which would show commit that changed line, disregarding whitespace-only change (like e.g. reindent caused by extracting code into separate function).

I wonder if it would be possible to generate result of "git blame" and of "git blame -C -C -w" in a single run (with --porcelain or --incremental)...

[...]
> And - for directories below the renamed one git log --follow 
> cannot cross this barrier either but if the "follow" logic
> is different I suppose this is not related

The implementation of "git log --follow <file>" is a bolted-on hack, and it doesn't work in all cases; for example it doesn't cross boundaries of subtree merge, IIRC. Try "git log --follow gitweb/gitweb.perl" in git repository itself...

HTH
-- 
Jakub Narebski
Poland
ShadeHawk on #git
Jakub Narebski· Mar 17, 2011, 16:47 UTC · re: Wolfgang Rohdewald · lore

Re: git blame --follow

Dnia czwartek 17. marca 2011 11:16, Wolfgang Rohdewald napisał:
> On Donnerstag 17 März 2011, Jakub Narebski wrote:
> > So you probably want to run "git blame -C -C <file>", not "git
> > blame <file>".
> 
> that does the trick - I only tried "git blame -C"

Hmmm... it is described in git-blame(1) manpage, but you have to read it carefully.

"git blame" synopsis states:
 'git blame' [-c] [-b] [-l] [--root] [-t] [-f] [-n] [-s] [-e] [-p] [-w] [--incremental] [-L n,m]
             [-S <revs-file>] [-M] [-C] [-C] [-C] [--since=<date>]
             [<rev> | --contents <file> | --reverse <rev>] [--] <file>
The important thing is to notice '[-C] [-C] [-C]' here.
In the description of '-C' option we have:
  -C|<num>|::
        In addition to `-M`, detect lines moved or copied from other
        files that were modified in the same commit.  This is
        useful when you reorganize your program and move code
        around across files.  When this option is given twice,
                              ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
        the command additionally looks for copies from other
        files in the commit that creates the file. When this
        option is given three times, the command additionally
        looks for copies from other files in any commit.
I have underlined important part.
-- 
Jakub Narebski
Poland

← back to recent threads