Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to grep (search) committed code in the Git history

Tags:

git

grep

diff

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.

like image 493
Ortwin Gentz Avatar asked May 28 '10 11:05

Ortwin Gentz


People also ask

How do I search for a commit in git log?

Looking up changes for a specific commit If you have the hash for a commit, you can use the git show command to display the changes for that single commit. The output is identical to each individual commit when using git log -p .

How do I search GitHub history?

Just type "git" and press tab in Chrome's address bar. You can search your browser history for GitHub URL you visited. This helps you to find and open GitHub repository, issues, pull requests, or etc.

Which command is used to find the specific commit in history?

The most basic and powerful tool to do this is the git log command. By default, with no arguments, git log lists the commits made in that repository in reverse chronological order; that is, the most recent commits show up first.


2 Answers

To search for commit content (i.e., actual lines of source, as opposed to commit messages and the like), you need to do:

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

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 in 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 -l -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>) 
like image 140
Jeet Avatar answered Sep 24 '22 14:09

Jeet


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. Example (from git log): git log -S"frotz\(nitfol" --pickaxe-regex


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

like image 33
VonC Avatar answered Sep 25 '22 14:09

VonC