git grep <regexp>
Try it out on a project, then try the same search with ack and grep and you see that we have speed that’s better than either grep or ack. First, we’ll make some improvements:
Allow Extended Regular Expressions
git config --global grep.extendRegexp true
git can also support full blown Perl regular expressions as well, by compiling git with libpcre. Easy for homebrew users:
brew install git --with-pcre
Always Include Line Numbers
git config --global grep.lineNumber true
Group Output Like Ack!
git config --global alias.g "grep --break --heading --line-number"
As far as I know there is no non-trivial way to add default arguments/override git commands, plus g is nice and short.
Compare this output, without grouping:
To this much more readable output, with grouping:
The speed of git grep, which is basically a product of it being implemented in C and only searching your project files, i.e. not files in .git, is alone very compelling, but where git grep becomes really interesting and powerful is allowing you to interface with your repo’s git database…
Here’s a list of commands made up of different arguments and concepts of git grep and git log that you will be able to reuse/use as instruction to reformulate later:
git grep -e <regexp> my_other_branch -- '*.js'
-- signals the end of options, that the rest of the paramaters are
Search files registered in the index, rather than the working tree:
git grep --cached -e <regexp>
Note that we’re searching what’s registered in the index rather than what is staged…
Search for staged files containing a regexp that was either added or removed:
git diff-index --cached -G<regexp> HEAD | cut -f2
Search through previous revisions whose contents contain a given regexp:
git grep <regexp> $(git rev-list --all)
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)
Search for commits whose changes include your regexp:
git log -G <regexp>
Combine regexps and filter results via boolean logic:
git grep -e 'include' --or 'extend' --and \( -e 'Specification' -e 'Factory' \)
Here we search for places that we extend or include, either specifications or factories.
Given this file, after running the command above we get:
Find files that contain some terms, not necessarily on the same line:
git grep -e <regexp> --and -e <regexp>
…is not what you want, as it will search for lines that contain both those regular expressions, this is what we want to search for all matches occurring somewhere in the file:
git grep --all-matches -e <regexp> -e <regexp>
Find commits whose message mention login and were authored by Travis in the last month:
git log --grep=login --author=travis --since=1.month
Text editor integration
Inevitably we will want to be able to search and use these programs from within our text editors.
Vim users have it pretty good, with both
ack.vim and Tim Pope’s
Fugitive which includes
interface with git grep by being to search and have your results listed and
linked in the quickfix window. By listing the results in the quickfix window
this mean you have the usual quickfix navigation keybindings, if you’re
If your project is not under git version control than you can use ack.vim in a similar manner:
Emacs user’s have had
vc-git-grep built-in since v22.1 and it’s very similar
:Ggrep. And for acking there is full-ack.
See this page (or
C-h f compliation-mode) for info on navigating in compilation-mode (the mode that both vc-git-grep and full-ack output into).
By now you are comfortable with git grep and git log, and can get more
details on each of these commands via
git help <command>, and have some useful tools in your repertoire, now have fun!