How to git grep
through whichever branches or commits you choose
Alright, with much effort, I figured it out. Here is how to do 4, 5, and 6:
- a range of commits
- a given commit all the way back to the parent commit
- all commits (and branches) in the entire repo
4. git grep
a range of commits
To search for "search string"
within a range of commits, from commit1
, inclusive, to commit2
, inclusive, do this:
IFS=$'\n' read -r -d '' -a commit_array <<< \
"$(git log --pretty=format:"%H" commit1~..commit2)"; \
git grep -n "search string" "${commit_array[@]}"
Here is an example that searches for "\bhey\b"
(\b
means "word boundary" in regular expressions) which you can run in my eRCaGuy_hello_world repo:
IFS=$'\n' read -r -d '' -a commit_array <<< \
"$(git log --pretty=format:"%H" f714d2fb18b00f0f423de98b6a7a418e42054cfe~..f396a4ae24153b35215335a1d6bf35ac843ad122)"; \
git grep -n "\bhey\b" "${commit_array[@]}"
Explanation
IFS=$'\n' read -r -d '' -a myarray <<< "$multiline_string"
converts a multiline string into a bash array named myarray
. See my answer here: How to read a multi-line string into a regular bash "indexed" array.
To get a range of commits, you can use this trick:
git log --pretty=format:%H fist_commit~..last_commit
Source where I got the necessary hints to learn the git log --pretty=format:%H
part: Get the short Git version hash.
Example usage and output, when in my eRCaGuy_hello_world repo. Here you can see the first commit I specify at the very bottom of the output, and the last commit at the very top:
eRCaGuy_hello_world$ git log --pretty=format:%H f714d2fb18b00f0f423de98b6a7a418e42054cfe~..f396a4ae24153b35215335a1d6bf35ac843ad122
f396a4ae24153b35215335a1d6bf35ac843ad122
d00f645cc56b5f4bf8b3c7b23c6ff62ca71734d7
0a795f56c2dd343e50d8c4f73f1347759ece9a08
f714d2fb18b00f0f423de98b6a7a418e42054cfe
5. git grep
a given commit all the way back to the parent commit
This command is a subset of the command above, and is even simpler. To search for "search string"
from commit
, inclusive, all the way back to the first (most-parent) commit, do this:
IFS=$'\n' read -r -d '' -a commit_array <<< \
"$(git log --pretty=format:"%H" commit)"; \
git grep -n "search string" "${commit_array[@]}"
Example from my eRCaGuy_hello_world repo:
IFS=$'\n' read -r -d '' -a commit_array <<< \
"$(git log --pretty=format:"%H" f396a4ae24153b35215335a1d6bf35ac843ad122)"; \
git grep -n "\bhey\b" "${commit_array[@]}"
6. git grep
a whole repository: ie: all commits (and branches) in the entire repo
Same as just above, except use --all
in place of the branch name or commit hash:
IFS=$'\n' read -r -d '' -a commit_array <<< \
"$(git log --pretty=format:"%H" --all)"; \
git grep -n "search string" "${commit_array[@]}"
Example from my eRCaGuy_hello_world repo:
IFS=$'\n' read -r -d '' -a commit_array <<< \
"$(git log --pretty=format:"%H" --all)"; \
git grep -n "\bhey\b" "${commit_array[@]}"
Alternative solutions and hints
A. To search for changes of a search pattern or word, you can do this:
- Search up from the current commit:
git log -S "some string"
- Search all branches:
git log --all -S "some string"
See: How can I search my ENTIRE git repo's commit history for a string change?.
B. To search through just the changes introduced by each commit, use git log -p
and search interactively through the less viewer:
You can also search for a match in your history like this: git log -p
, then press the / key, type your regular expression search string, and press Enter. Press n for "next match" or Shift + n for "previous match". The -p
in git log
shows the changes in "patch" format for each commit. And, since the output of git log
is viewed in the less
viewer, you can use it to search the contents interactively.
C. Use git log --grep <regex> <branches>
...as described here: Search a whole Git repository.