Using git to find first introduction of token on a specific line of a file
Asked Answered
J

5

13

Let's say I have a file A.cpp, and I notice an error on line 15 of the file. Let's say the error is a "const" on a function that returns a pointer to a member variable, meaning using const on the function is technically correct but semantically wrong. I would like to discuss the semantics with the author who made the change.

Using git, is there a way to find out which revision introduced the "const" token? More specifically, I'd like to know who introduced the token.

"git blame" shows who made the last change to the line, but I would actually like to find the first commit containing the token.

Jones answered 7/12, 2009 at 22:35 Comment(3)
Can you not diff each revision until it shows up? Sorry, I don't know much about Git, but that's what I'd do for other source control systems.Bisectrix
Yes, but that could be very time consuming... the history for the repository goes back at least 3 years with several thousand commits on this file. This seems like a fairly common task, it seems like there would be a better way to do this.Jones
See also git: finding a commit that introduced a string.Vestpocket
T
13

git bisect is what you are looking for. With this command you can find quickly what commit introduced the const.

You start the process with git bisect start, then mark an old version without the const as good with git bisect good and and the current one as bisect bad. Then the system will send you to a version in the middle. You can check if the evil const is there, and mark that version good or bad depending on it. Then The process is repeated until you find the bad commit.

Trin answered 7/12, 2009 at 22:43 Comment(1)
If you can write a simple script that exits with 1 if the constant is there (i.e. a "bad" state), call git bisect run myscript, sit back and enjoy git doing the job for you...Xiomaraxiong
T
28

There are a few possible ways of doing it.

  • git blame, or better graphical blame tool (like git gui blame or the blame view in git instaweb / gitweb) to browse history of a line, going back in history until you find appropriate commit.

  • so called "pickaxe search", i.e. git log -S with appropriate token / regexp, to find (list) all commits where number of given tokens changed (which usually means where given token was added or deleted), e.g.:

    git log --reverse -p -S'const int foobar' -- A.cpp
    
  • git bisect where "bad" commit would mean the one with 'const' where there it shouldn't be (testing using e.g. grep).

Tisbee answered 8/12, 2009 at 1:31 Comment(0)
T
13

git bisect is what you are looking for. With this command you can find quickly what commit introduced the const.

You start the process with git bisect start, then mark an old version without the const as good with git bisect good and and the current one as bisect bad. Then the system will send you to a version in the middle. You can check if the evil const is there, and mark that version good or bad depending on it. Then The process is repeated until you find the bad commit.

Trin answered 7/12, 2009 at 22:43 Comment(1)
If you can write a simple script that exits with 1 if the constant is there (i.e. a "bad" state), call git bisect run myscript, sit back and enjoy git doing the job for you...Xiomaraxiong
F
4

The change may not have always been on line 15 of A.cpp, so use the surrounding context. Say it was a definition of const int foobar:

git grep 'const *int *foobar' \
  $(git log --reverse --pretty=format:%H -- A.cpp) -- \
  A.cpp | head -1

This searches forward in time through all commits on the current branch that touch A.cpp and finds the first one that contains the offending pattern. The output will be the commit's SHA-1 and the matching line in its revision of A.cpp.

Once you know the commit, use git show to learn the author.

Fleeman answered 7/12, 2009 at 23:2 Comment(0)
P
1

I use QGit for this, select the lines of interest, and filter on that, then you see only the list of change for that line. For a single line it's not to had to jump around a few revisions.

via:

  • open QGit on repository
  • open Tree view
  • find file
  • find line
  • select line of interest
  • press 'filter revision of selected lines' button, looks like a funnel.
Penutian answered 7/12, 2009 at 22:40 Comment(0)
D
1

If the line existed without the const token in some commit that you know, you can start there and use the --reverse flag on git-blame to find the last revision in which the line didn't have the const token. Then just look at the next revision on the file after that.

Deadfall answered 7/12, 2009 at 22:41 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.