Is it possible to run git grep
inside all the branches of a Git control sourced project? Or is there another command to run?
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>
Jan. 2024: Gabriel Staples adds in the comments:
For anyone who wants to search just the tip commits on every branch in the repo, rather than every commit in the repo, and if you'd like to do parallel processes to speed up the search, see my very extensive answer here:
All about searching (via
grep
or similar) in your git repositories.
I build upon some of the content in this answer.
git branch
into tr or sed; git branch
is a porcelain command meant for human consumption. See https://mcmap.net/q/12335/-how-to-iterate-through-all-git-branches-using-bash-script for preferred alternatives. –
Divisor git rev-list --all
command. You won't have to press any key. (unix.stackexchange.com/a/117502/7490) –
Beadle grep.extendRegexp
should be grep.extendedRegexp
–
Crow grep
or similar) in your git repositories. I build upon some of the content in this answer. –
Fabozzi 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
git rev-list --all
approach took several minutes. The output is more useful too (includes the diff). –
Lynelllynelle 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/)'
git for-each-ref
with --sort=-committerdate --count=100
! Thanks for the original idea! –
Fiddlewood 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"
1. Grep: using Git aliases
In 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.
Explanation:
git branch -a
- Display all branches;sed -e 's/[ \\*]*//'
- Trim spaces (frombranch -a
) and*
, which is shown in front of the active branch name;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)
2. 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"
git grep-branch "find my text"
: fatal: ambiguous argument 'client': both revision and filename
–
Avatar -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 –
Cyrilcyrill cleanLocalBranches = "!f(){ git branch -a | egrep -v '(^\\*|master|dev)' | xarg s git branch -D; };f "
–
Perhaps 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
Here's how I do it:
git for-each-ref --format='%(*refname)' | xargs git grep SEARCHTERM
© 2022 - 2024 — McMap. All rights reserved.