13

I am trying to trace a piece of code (just a single line) to it's commit.

Using blame only points me to a commit where this line in question was moved as a part of an extract method style refactoring.

What techniques can I use to get to the commit were that particular text existed in the codebase for the first time?

zadam
  • 2,416
  • 2
  • 23
  • 32
  • Does `-C` and/or `-M` to `git blame` work for you? `git blame` is showing you the first existence, but you want to ignore moves: but what counts as a move? It's a bit fuzzy, which is why `git blame` doesn't do it by default, I think. – Thanatos Mar 07 '14 at 06:00
  • Possible duplicate of [git: finding a commit that introduced a string](http://stackoverflow.com/questions/5816134/git-finding-a-commit-that-introduced-a-string) and also [Using git to find first introduction of token on a specific line of a file](http://stackoverflow.com/questions/1863393/using-git-to-find-first-introduction-of-token-on-a-specific-line-of-a-file). –  Mar 07 '14 at 07:14
  • Recursively blaming the file is the manual/normal way (blame, che kout parent commit, blame etc) – AD7six Mar 07 '14 at 08:30
  • @AD7six `git log -S ` or `git log -G ` is much more efficient, and less work. –  Mar 07 '14 at 10:37

3 Answers3

17

As noted in this answer to git: finding a commit that introduced a string, you can simply use

git log -S <line>
# or
git log -G <regex>

to find the first occurrence of a line of code in a repository.

From the official Linux kernel Git documentation for log:

-S<string>

Look for differences that introduce or remove an instance of <string>. Note that this is different than the string simply appearing in diff output; see the pickaxe entry in gitdiffcore(7) for more details.

-G<regex>

Look for differences whose added or removed line matches the given <regex>.

Community
  • 1
  • 1
0

I usually do git log -p filename and search (pressing /) for the given text.

This way you notice changes of that line and you can continue searching for a (slightly) different text if the text changed in the past.

michas
  • 25,361
  • 15
  • 76
  • 121
  • 1
    You can ***eventually*** find the first occurrence of a line this way, but it can be very inefficient and time-consuming. Using `git log -S ` or `git log -G ` is much faster and efficient. –  Mar 07 '14 at 10:30
  • Yes, other options might be faster, but this way you have the whole context of all commits for that file. – michas Aug 13 '14 at 11:14
-1

I would probably settle for:

function allcommits { 
    git rev-list --reverse HEAD
}


for i in `allcommits` ;do  
    git co -f $i 2>/dev/null ; 
    echo commit:$i ;
    git grep -q 'that line of code' && break
done

You check out every commit starting with the first one, and scan all files in each step, until you find a match.

Chandrayya G K
  • 8,719
  • 5
  • 40
  • 68