Additions and updates to a line are easy, because you can just git blame on the file in question and find who and/or what is responsible for the latest change. However, it’s hard to git blame a line that was removed, right?
git log -S<string>
Look for differences that change the number of occurrences of the specified <string> (i.e. addition/deletion) in a file. Intended for the scripter’s use.
It is useful when you’re looking for an exact block of code (like a struct), and want to know the history of that block since it first came into being: use the feature iteratively to feed the interesting block in the preimage back into
-S, and keep going until you get the very first version of the block.Binary files are searched as well.
You can use git log with the -S option (pickaxe) to find when “uuidtools” was removed:
git log -S"uuidtools" --oneline -- chef.gemspec
This will show all commits that added or removed “uuidtools” from chef.gemspec. The commit where it was removed will show the line disappearing.
For more detail, add -p to see the actual changes:
git log -S"uuidtools" -p -- chef.gemspec
If you want to search specifically on the main branch:
git log main -S"uuidtools" -p -- chef.gemspec
The -S option finds commits where the number of occurrences of “uuidtools” changed, so you’ll see both when it was added and when it was removed.
What if I want to use a regex?
git log -G<regex>
Look for differences whose patch text contains added/removed lines that match <regex>.
To illustrate the difference between
-S<regex>--pickaxe-regexand-G<regex>, consider a commit with the following diff in the same file:+ return frotz(nitfol, two->ptr, 1, 0); ... - hit = frotz(nitfol, mf2.ptr, 1, 0);
You can use git log with the -G option to search by regex:
git log -G"uuidtools" --oneline -- chef.gemspec
The -G option looks for commits where the regex matches in the diff, rather than just counting occurrences like -S does.
For more detailed output with the actual changes:
git log -G"uuidtools" -p -- chef.gemspec
Or on the main branch specifically:
git log main -G"uuidtools" -p -- chef.gemspec
The difference between -G and -S:
-G<regex>: Finds commits where the regex matches any added or removed line-S<string>: Finds commits where the number of occurrences of the string changed
So -G is more flexible and will catch any line change matching your pattern, even if the total count stays the same.