git grep: Usage, Options & Common CI Errors
git grep searches the contents of tracked files (or any revision) much faster than plain grep over a checkout.
git grep is the right search tool in a repo: it skips ignored files and can search any commit, not just the working tree.
What it does
git grep searches the working tree, the index, or a given revision for a pattern, limited to tracked files, using Git’s fast threaded search.
Common usage
git grep "TODO"
git grep -n -i "deprecated" # line numbers, case-insensitive
git grep -l "apiKey" # file names only
git grep "needle" HEAD~5 # search a past revision
git grep -e foo --and -e barOptions
| Flag | What it does |
|---|---|
| -n / --line-number | Show line numbers |
| -l / --files-with-matches | List matching file names |
| -i / --ignore-case | Case-insensitive search |
| -e <pattern> | Specify a pattern (combine with --and/--or) |
| --cached | Search the index instead of the working tree |
Common errors in CI
git grep exits 1 when there are no matches, which CI may treat as a failure - handle it deliberately (e.g. fail the build if a forbidden string IS found: ! git grep -q "console.log"). fatal: not a git repository means it was run outside a checkout.
Using this in CI
CI checkouts are shallow and detached by default, which changes the answer this command gives you. Commands that read history, branch names, or tags need the checkout configured for it.
- uses: actions/checkout@v4
with:
fetch-depth: 0 # history, tags, and git describe all need this
- run: |
git rev-parse --is-shallow-repository # expect false
git rev-parse --abbrev-ref HEAD # prints HEAD when detached