Skip to content

Instantly share code, notes, and snippets.

Embed
What would you like to do?
Search Git commit history for a string and see the diffs

Searching Git commit history

This should be one of the core features of Git, but for some reason it's impossible to figure out how to search for a string in your commit history and see the diffs that that string is in. Here's the best I've come up with:

To find which commits and which files a string was added or removed in:

git log -S'search string' --oneline --name-status

To see the diff of that

git log -S'search string' -p | grep 'search string' -C5

You can also do a regex search by using -G instead of -S.

@benknoble
Copy link

benknoble commented Oct 5, 2018

log takes a patch-with-stat option

@raedbenz
Copy link

raedbenz commented Jan 4, 2019

@0xdevalias
Copy link

0xdevalias commented Jun 22, 2021

On that same StackOverflow issue that @raedbenz linked, there is a better answer that basically suggests the same -S 'pickaxe' method described here + goes into some more details about it's usage:

Since I always find myself ending up back on this gist, here are the methods described in that StackOverflow:

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.


Looking at the StackOverflow for case-insensitive pickaxes search:

The way the -i is used with pickaxe (see commit accccde, git 1.7.10, April 2012) is:

git log -S foobar -i --oneline
# or
git log --regexp-ignore-case -Sfoobar
# or
git log -i -Sfoobar

Note that with 1.x git versions this option will not work with a regexps, only with a fixed string. It works with regexps only since git 2.0 and commit 218c45a, git 2.0, May 2014.


From:

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.

You can combine -p / --patch with any of these methods to get a diff patch of the found commits.


Hopefully saves someone else (or future me) some time! 🖤

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment