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
.
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:
* https://stackoverflow.com/questions/2928584/how-to-grep-search-committed-code-in-the-git-history/2928721#2928721
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 ofgit 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 (fromgit 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! 🖤