How to grep (search) committed code in the git history?

I have deleted a file or some code in a file sometime in the past. Can I grep in the content (not in the commit messages)?

A very poor solution is to grep the log:

git log -p | grep <pattern>

However this doesn't return the commit hash straight away. I played around with git grep to no avail.


To search for commit content (ie, actual lines of source, as opposed to commit messages and the like), what you need to do is:

git grep <regexp> $(git rev-list --all)

Updates : git rev-list --all | xargs git grep expression git rev-list --all | xargs git grep expression will work if you run into an "Argument list too long" error

If you want to limit the search to some subtree (for instance "lib/util") you will need to pass that to the rev-list subcommand and grep as well:

git grep <regexp> $(git rev-list --all -- lib/util) -- lib/util

This will grep through all your commit text for regexp.

The reason for passing the path in both commands is because rev-list will return the revisions list where all the changes to lib/util happened, but also you need to pass to grep so that it will only search on lib/util .

Just imagine the following scenario: grep might find the same <regexp> on other files which are contained in the same revision returned by rev-list (even if there was no change to that file on that revision).

Here are some other useful ways of searching your source:

Search working tree for text matching regular expression regexp:

git grep <regexp>

Search working tree for lines of text matching regular expression regexp1 or regexp2:

git grep -e <regexp1> [--or] -e <regexp2>

Search working tree for lines of text matching regular expression regexp1 and regexp2, reporting file paths only:

git grep -e <regexp1> --and -e <regexp2>

Search working tree for files that have lines of text matching regular expression regexp1 and lines of text matching regular expression regexp2:

git grep -l --all-match -e <regexp1> -e <regexp2>

Search working tree for changed lines of text matching pattern:

git diff --unified=0 | grep <pattern>

Search all revisions for text matching regular expression regexp:

git grep <regexp> $(git rev-list --all)

Search all revisions between rev1 and rev2 for text matching regular expression regexp:

git grep <regexp> $(git rev-list <rev1>..<rev2>)

You should use the pickaxe ( -S ) option of git log

To search for Foo :

git log -SFoo -- path_containing_change 
git log -SFoo --since=2009.1.1 --until=2010.1.1 -- path_containing_change

See Git history - find lost line by keyword for more.


As Jakub Narębski commented:

  • this looks for differences that introduce or remove an instance of <string> .
    It usually means "revisions where you added or removed line with 'Foo'".

  • the --pickaxe-regex option allows you to use extended POSIX regex instead of searching for a string.


  • As Rob commented, this search is case-sensitive - he opened a follow-up question on how to search case-insensitive.


    My favorite way to do it is with git log 's -G option (added in version 1.7.4).

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

    There is a subtle difference between the way the -G and -S options determine if a commit matches:

  • The -S option essentially counts the number of times your search matches in a file before and after a commit. The commit is shown in the log if the before and after counts are different. This will not, for example, show commits where a line matching your search was moved.
  • With the -G option, the commit is shown in the log if your search matches any line that was added, removed, or changed.
  • Take this commit as an example:

    diff --git a/test b/test
    index dddc242..60a8ba6 100644
    --- a/test
    +++ b/test
    @@ -1 +1 @@
    -hello hello
    +hello goodbye hello
    

    Because the number of times "hello" appears in the file is the same before and after this commit, it will not match using -Shello . However, since there was a change to a line matching hello , the commit will be shown using -Ghello .

    链接地址: http://www.djcxy.com/p/3314.html

    上一篇: 使用grep时获取行号

    下一篇: 如何在git历史中grep(搜索)提交的代码?