Is it possible to run git grep
inside all the branches of a Git control sourced project? Or is there another command to run?

- 30,738
- 21
- 105
- 131

- 11,279
- 21
- 61
- 85
-
5possible duplicate of [Using git, how could I search for a string across all branches?](http://stackoverflow.com/questions/7151311/using-git-how-could-i-search-for-a-string-across-all-branches) – Ciro Santilli OurBigBook.com Feb 20 '15 at 13:59
-
Possible duplicate of [How to grep (search) committed code in the git history?](https://stackoverflow.com/questions/2928584/how-to-grep-search-committed-code-in-the-git-history) – rofrol Oct 19 '18 at 14:45
-
The [second answer](https://stackoverflow.com/a/26226807/633961) is the best. – guettli Dec 07 '21 at 15:59
6 Answers
The question "How to grep (search) committed code in the Git history?" recommends:
git grep <regexp> $(git rev-list --all)
That searches through all the commits, which should include all the branches.
Another form would be:
git rev-list --all | (
while read revision; do
git grep -F 'yourWord' $revision
done
)
You can find even more example in this article:
I tried the above on one project large enough that git complained about the argument size, so if you run into this problem, do something like:
git rev-list --all | (while read rev; do git grep -e <regexp> $rev; done)
(see an alternative in the last section of this answer, below)
Don't forget those settings, if you want them:
# Allow Extended Regular Expressions
git config --global grep.extendedRegexp true
# Always Include Line Numbers
git config --global grep.lineNumber true
This alias can help too:
git config --global alias.g "grep --break --heading --line-number"
Update August 2016: R.M. recommends in the comments
I got a "
fatal: bad flag '->' used after filename
" when trying thegit branch
version. The error was associated with aHEAD
aliasing notation.I solved it by adding a
sed '/->/d'
in the pipe, between thetr
and thexargs
commands.git branch -a | tr -d \* | sed '/->/d' | xargs git grep <regexp>
That is:
alias grep_all="git branch -a | tr -d \* | sed '/->/d' | xargs git grep"
grep_all <regexp>
This is an improvement over the solution chernjie had suggested, since git rev-list --all
is an overkill.
A more refined command can be:
# Don't use this, see above git branch -a | tr -d \* | xargs git grep <regexp>
Which will allow you to search only branches (including remote branches)
You can even create a bash/zsh alias for it:
# Don't use this, see above alias grep_all="git branch -a | tr -d \* | xargs git grep" grep_all <regexp>

- 1,262,500
- 529
- 4,410
- 5,250
-
It's not a good idea to pipe the output of `git branch` into tr or sed; `git branch` is a porcelain command meant for human consumption. See http://stackoverflow.com/a/3847586/2562319 for preferred alternatives. – jbyler May 11 '17 at 19:50
-
@jbyler Good point. Ironically, I posted the answer on porcelain long before this answer: http://stackoverflow.com/a/6978402/6309. And I use it for instance in http://stackoverflow.com/a/19206916/6309. – VonC May 11 '17 at 19:54
-
Yep, nice. Looking through the other answers, I think the answer by @errordeveloper is the cleanest: http://stackoverflow.com/a/21284342/2562319 : "git grep
$(git for-each-ref --format='%(refname)' refs/)" – jbyler May 11 '17 at 20:05 -
9Is there any way to show the name of the branch that matched the search? – franksands Oct 16 '18 at 16:26
-
What does "while read rev; do git grep -e
$rev; done" do exactly? Must I press a key to continue viewing? – Emmanuel Goldstein Nov 28 '20 at 08:27 -
@EmmanuelGoldstein It will read each lines of the `git rev-list --all` command. You won't have to press any key. (https://unix.stackexchange.com/a/117502/7490) – VonC Nov 28 '20 at 12:10
-
Yes, I have. In fact, when I press 'q' I see every time a different commit. So this is confusing. The above command will only display one result per page, at least on my end. – Emmanuel Goldstein Nov 29 '20 at 05:54
-
-
1@AdmiralAdama thank you for the feedback. I have edited the answer accordingly. – VonC Nov 11 '22 at 00:54
-
-
@VonC Yes AdmiralAdama. As usual, all hail King VonC of the git kingdom. Let all those who benefit from his solutions pay sufficient tribute to the great one! – Nathan majicvr.com Jun 12 '23 at 17:20
git log
can be a more effective way of searching for text across all branches, especially if there are many matches, and you want to see more recent (relevant) changes first.
git log -p --all -S 'search string'
git log -p --all -G 'match regular expression'
These log commands list commits that add or remove the given search string/regex, (generally) more recent first. The -p
option causes the relevant diff to be shown where the pattern was added or removed, so you can see it in context.
Having found a relevant commit that adds the text you were looking for (eg. 8beeff00d), find the branches that contain the commit:
git branch -a --contains 8beeff00d

- 13,591
- 4
- 52
- 48
-
-
1Yes, this returned almost immediately while the `git rev-list --all` approach took several minutes. The output is more useful too (includes the diff). – markfickett Aug 10 '22 at 14:46
I found this most useful (omit -i
if you desire a case-sensitive search):
git grep -i foo `git for-each-ref --format='%(refname)' refs/`
You'd need to adjust the last arguments depending on whether you want to only look at remote vs. local branches, i.e.:
git grep -i foo $(git for-each-ref --format='%(refname)' refs/remotes)
git grep -i foo $(git for-each-ref --format='%(refname)' refs/heads)
The alias I created looks like this:
grep-refs = !sh -c 'git grep "$0" "$@" "$(git for-each-ref --format=\"%(refname)\"" refs/)'

- 3,386
- 2
- 19
- 42

- 6,716
- 6
- 41
- 54
-
1
-
How to make your alias to work for phrase search? When I pass "foo bar" as a parameter, I get: fatal: ambiguous argument 'bar': unknown revision or path not in the working tree. Use '--' to separate paths from revisions – jutky Apr 06 '16 at 11:58
-
-
This shall clearly be the accepted answer ;) I've expanded on it to search only across the latest branches of my project (Got more than 500, don't ask, and each grep takes about 4sec so I don't want nor need to search across more than the, say, 100 latest of them). For this I've updated the `git for-each-ref` with `--sort=-committerdate --count=100` ! Thanks for the original idea! – Vser Jan 29 '20 at 09:52
It's possible to do it in two common ways: Bash or Git aliases
Here are three commands:
git grep-branch
- Search in all branches local & remotegit grep-branch-local
- Search in local branches onlygit grep-branch-remote
- Remote branches only
Usage is the same as git grep
git grep-branch "find my text"
git grep-branch --some-grep-options "find my text"
GREP using: Git aliases
File ~/.gitconfig
Commands should be added manually to ~/.gitconfig
file, because git config --global alias
evaluate complex code you add and mess it up.
[alias]
grep-branch = "!f(){ git branch -a | sed -e 's/[ \\*]*//' | grep -v -e '\\->' | xargs git grep $@; };f "
grep-branch-remote = "!f(){ git branch -a | sed -e 's/[ \\*]*//' | grep -v -e '\\->' | grep '^remotes' | xargs git grep $@; };f"
grep-branch-local = "!f(){ git branch -a | sed -e 's/[ \\*]*//' | grep -v -e '\\->' -e '^remotes' | xargs git grep $@; };f "
Note: When you add aliases and they fail to run - check backslashes \
they may require additional escape \\
in compare to bash commands.
git branch -a
- Display all branches;sed -e 's/[ \\*]*//'
- Trim spaces (frombranch -a
) and * (active branch name have it);grep -v -e '\\->'
- Ignore complex names likeremotes/origin/HEAD -> origin/master
;grep '^remotes'
- Get all remote branches;grep -v -e '^remotes'
- Get branches except remote branches;
Example git grep-branch-local -n getTastyCookies
-n
Prefix the line number to matching lines.
[user@pc project]$ git grep-branch-local -n getTastyCookies
dev:53:modules/factory/getters.php:function getTastyCookies($user);
master:50:modules/factory/getters.php:function getTastyCookies($user)
The current structure is:
:
- Separator
- Branch:
dev
- Line number:
53
- File path:
modules/factory/getters.php
- Matching line:
function getTastyCookies($user)
GREP using: BASH
As you should know: Bash commands should be stored in .sh
scripts or run in a shell.
Local branches only
git branch -a | sed -e 's/[ \*]*//' | grep -v -e '\->' -e '^remotes' | xargs git grep "TEXT"
Remote branches only
git branch -a | sed -e 's/[ \*]*//' | grep -v -e '\->' | grep '^remotes' | xargs git grep "TEXT"
Local & remote branches
git branch -a | sed -e 's/[ \*]*//' | grep -v -e '\->' | xargs git grep "TEXT"

- 30,738
- 21
- 105
- 131

- 91
- 1
- 5
-
Sounds nice, but I got this error from `git grep-branch "find my text"`: `fatal: ambiguous argument 'client': both revision and filename` – nealmcb Aug 06 '17 at 15:16
-
Why always use `-a`, which shows all branches? I would suggest using options to the `git branch` command to separate braches. When looking at local branches, there's only a single `*`, so no need to escape it for sed. So: `git branch | sed -e 's/*/ /' | xargs git grep "TEXT"` for local branches only, `git branch -r | grep -v -- "->" | xargs git grep "TEXT"` for remote branches only, and `git branch -a | grep -v -- "->" | xargs git grep "TEXT"` for all branches – jalanb May 06 '20 at 01:25
-
I had a slightly different problem, but that this weird function thing solved my problem. thank you! and just for reference - I wanted to delete all local branches apart from master and dev. the alias to do that is: `cleanLocalBranches = "!f(){ git branch -a | egrep -v '(^\\*|master|dev)' | xarg s git branch -D; };f "` – WrRaThY Mar 23 '22 at 20:56
If you give any commit a SHA-1 hash value to git grep
you have it search in them, instead of the working copy.
To search all branches, you can get all the trees with git rev-list --all
. Put it all with
git grep "regexp" $(git rev-list --all)
... and have patience

- 30,738
- 21
- 105
- 131

- 86,532
- 28
- 194
- 218
Here's how I do it:
git for-each-ref --format='%(*refname)' | xargs git grep SEARCHTERM

- 37,208
- 23
- 149
- 195