My company uses multiple git repos that all depend on one another. Often I find myself trying to grep through a few of them at the same time.
Regular grep works, but it takes a long time and displays a lot of noise.
git grep only searches through files that are NOT listed in
.gitignore file, but only works at per-repo level.
Few months ago I wrote a script to walk through my repos and generate a list of things I worked on that week.
I’ve modified that script to do
git grep for all git repos.
git-grep-all "some string" will produce:
/some/file: some string
/some/other/file: some string 123
/yet/another/file: again some string
git-grep-all TODO will produce the following result.
grep-demo$ git-grep-all TODO
/Users/akras/Desktop/grep-demo/preact/config/codemod-let-name.js:8: // @TODO unsafe, but without it we gain 20b gzipped: https://www.diffchecker.com/bVrOJWTO
/Users/akras/Desktop/grep-demo/preact/test/browser/lifecycle.js:504: // @TODO Component mounted into elements (non-components)
/Users/akras/Desktop/grep-demo/preact/test/browser/spec.js:97: // @TODO: migrate this to preact-compat
/Users/akras/Desktop/grep-demo/rendertron/src/cache.js:29: // TODO(samli): check info (data) and loop through pages of entities to delete.
/Users/akras/Desktop/grep-demo/rendertron/src/cache.js:107:// TODO(samli): Allow for caching options, like freshness options.
/Users/akras/Desktop/grep-demo/rendertron/src/renderer.js:56: // TODO(samli): This needs to change to use the non-deprecated API after Chrome 61
/Users/akras/Desktop/grep-demo/vue/benchmarks/dbmon/lib/memory-stats.js:61: // TODO, add a sanity check to see if values are bucketed.
/Users/akras/Desktop/grep-demo/vue/packages/weex-vue-framework/factory.js:6383: // TODO: record before patch positions
/Users/akras/Desktop/grep-demo/vue/packages/weex-vue-framework/factory.js:6417: // TODO: finish implementing move animations once
/Users/akras/Desktop/grep-demo/vue/src/platforms/weex/runtime/components/transition-group.js:63: // TODO: record before patch positions
/Users/akras/Desktop/grep-demo/vue/src/platforms/weex/runtime/components/transition-group.js:97: // TODO: finish implementing move animations once
Few notes to get it working
- You need to update the BASE variable. All my git repo are nested under one folder, and it looks as follows:
- I’ve saved this file to ~/bin/git-grep-all, made it executable, and added ~/bin to my PATH.
- Now I can just run
git-grep-all "my search string"to search through all repos that I have cloned.
BASE = 'path/to/multiple/repos/to/search/' # <----------- Fix base path
if len(sys.argv) < 2:
print 'used as: grep-all "some string"'
search = sys.argv
repos = os.listdir(BASE)
repos = [os.path.join(BASE, repo) for repo in repos]
results = ""
for dir in repos:
command = 'cd ' + dir + ' && git grep --color="always" \'' + search + '\''
results = commands.getstatusoutput(command)
len(results) > 0 and
"Not a directory" not in results and
"Not a git repository" not in results
print "\n" + os.path.relpath(dir, BASE)
Note: This method is not perfect. It will only grep repos at the state that you last left them in and it will not pull new changes from
origin. Still, I find that it works really well for 80% of my use cases.
Hope it helps.