Searching Project Content with git grep
Large projects may contain hundreds or thousands of files.
Suppose we are working on a Laravel login feature and want to answer questions such as:
- Where is
AuthServiceused? - Which files contain
TODOcomments? - Where is the
loginmethod called? - Which PHP files mention
password? - Which tests use
LoginRequest?
Opening every file manually would be slow.
Git provides the following command:
git grepIt searches for matching text patterns inside project files known to Git.
The general form is:
git grep "search pattern"For example:
git grep "AuthService"git grep is a read-only command. It searches and displays matching content,
but it does not modify:
- The Working Tree.
- The Staging Area.
- Existing commits.
- Repository history.
What does grep mean?
Section titled “What does grep mean?”The important beginner idea is:
grepsearches text and prints lines that match a pattern.
When we use it through Git:
git grepGit performs the search using its knowledge of the repository.
What does git grep search by default?
Section titled “What does git grep search by default?”By default, git grep searches the contents of tracked files in the Working
Tree. Tracked files are files Git already knows about.
Search pattern
The text you are looking for, such as AuthService.
Tracked files
The Working Tree versions of files Git already tracks.
Matching lines
Displayed as file path, line, and content.
It does not search untracked files by default, and it does not search every previous commit in repository history by default.
It would be inaccurate to say that git grep searches every file and every
commit in the repository — that is not the default behavior.
Practical Laravel example
Section titled “Practical Laravel example”Suppose our Laravel project contains these files:
app/├── Http/│ └── Controllers/│ └── AuthController.php├── Services/│ └── AuthService.php└── Providers/ └── AppServiceProvider.php
tests/└── Feature/ └── LoginTest.phpInside the project, the text AuthService appears in several places. Run:
git grep "AuthService"An illustrative result may look like:
app/Http/Controllers/AuthController.php:use App\Services\AuthService;app/Http/Controllers/AuthController.php:public function __construct(private AuthService $authService)app/Providers/AppServiceProvider.php:AuthService::class,app/Services/AuthService.php:class AuthServicetests/Feature/LoginTest.php:AuthService::classOne result reads as follows:
app/Services/AuthService.php:class AuthServiceIt contains:
- The path of the file:
app/Services/AuthService.php - The matching line:
class AuthService
The colon separates the displayed file path from the matching content. The exact paths and output depend on the learner’s own project.
Search is case-sensitive by default
Section titled “Search is case-sensitive by default”A basic search is normally case-sensitive. These patterns are not necessarily treated as identical:
AuthServiceauthserviceAUTHSERVICEFor example:
git grep "authservice"may not find AuthService when their letter case differs.
To ignore letter case, use:
git grep -i "authservice"The long form is:
git grep --ignore-case "authservice"An illustrative result may contain:
app/Services/AuthService.php:class AuthServicetests/Feature/LoginTest.php:AuthService::class-imeans ignore case.- It allows uppercase and lowercase forms to match.
- It changes how the search is performed. It does not modify the source files.
Show line numbers with -n
Section titled “Show line numbers with -n”When we find a result, we often need to know its line number. Use:
git grep -n "AuthService"The long form is:
git grep --line-number "AuthService"Illustrative output:
app/Http/Controllers/AuthController.php:8:use App\Services\AuthService;app/Services/AuthService.php:10:class AuthServicetests/Feature/LoginTest.php:14:AuthService::classOne result reads as follows:
app/Services/AuthService.php:10:class AuthServiceThe parts are:
File path → app/Services/AuthService.phpLine number → 10Matching line → class AuthService
-nis one of the most useful options because it tells us exactly where to open the file.
The example’s line numbers will not necessarily match every project — they depend on the actual file content.
Combine useful options
Section titled “Combine useful options”Options can be combined. For example:
git grep -ni "authservice"This means:
-n: show line numbers.-i: ignore letter case.
Illustrative output:
app/Http/Controllers/AuthController.php:8:use App\Services\AuthService;app/Services/AuthService.php:10:class AuthServiceThis is equivalent to:
git grep -n -i "authservice"Search for a complete word with -w
Section titled “Search for a complete word with -w”Sometimes a short pattern appears inside longer words. Suppose the project contains:
loginloginUserLoginControllerRunning:
git grep "login"may match text containing login as part of a longer word.
To match login at word boundaries, use:
git grep -w "login"The long form is:
git grep --word-regexp "login"-w is useful when we want the word itself rather than every larger word
containing the same characters. It does not search for a complete line — it
matches at word boundaries.
Display only filenames with -l
Section titled “Display only filenames with -l”Sometimes we do not need every matching line — we may only want to know which
files contain AuthService. Use:
git grep -l "AuthService"The long form is:
git grep --files-with-matches "AuthService"Illustrative output:
app/Http/Controllers/AuthController.phpapp/Providers/AppServiceProvider.phpapp/Services/AuthService.phptests/Feature/LoginTest.php- The matching lines are hidden.
- Each matching filename is displayed once.
- This is useful when we want a quick list of affected or related files.
-l does not display line numbers — it displays filenames only.
Limit the search to one directory
Section titled “Limit the search to one directory”We may want to search only inside the application code and ignore the test files. Use:
git grep -n "AuthService" -- app/Illustrative output:
app/Http/Controllers/AuthController.php:8:use App\Services\AuthService;app/Services/AuthService.php:10:class AuthServiceThe command breaks down as:
git grepperforms the search.-ndisplays line numbers."AuthService"is the search pattern.--ends the list of command options.app/is the pathspec limiting the search location.
Content before
--describes how to search. Paths after--describe where to search.
The -- separator is not mandatory in every simple git grep command, but it
makes the separation between options and paths explicit and prevents
ambiguity.
Limit the search to PHP files
Section titled “Limit the search to PHP files”To search only inside tracked PHP files, use:
git grep -n "AuthService" -- '*.php'"AuthService"is the text pattern.--separates the search arguments from the pathspec.'*.php'limits the search to matching PHP paths.- The quotes prevent the shell from expanding the wildcard before Git receives it.
Illustrative output:
app/Http/Controllers/AuthController.php:8:use App\Services\AuthService;app/Services/AuthService.php:10:class AuthServicetests/Feature/LoginTest.php:14:AuthService::classSearch inside a directory and file extension together
Section titled “Search inside a directory and file extension together”To search only PHP files inside app/, use:
git grep -n "AuthService" -- 'app/**/*.php'This pathspec limits the search to matching PHP files inside app/. If your
shell or Git version does not accept this pattern, the simpler
directory-limited form works reliably:
git grep -n "AuthService" -- app/Search for TODO comments
Section titled “Search for TODO comments”A common practical task is finding unfinished work:
git grep -n "TODO"Illustrative output:
app/Services/AuthService.php:24:// TODO: add login attempt throttlingapp/Http/Controllers/AuthController.php:31:// TODO: move response formattinggit grep does not understand the meaning of TODO — it simply searches for
matching text.
Search for an error message
Section titled “Search for an error message”Suppose a user reports this message:
Invalid credentialsWe can search for the text:
git grep -n "Invalid credentials"Illustrative output:
app/Services/AuthService.php:36:throw ValidationException::withMessages(['email' => 'Invalid credentials']);This can help us locate the code responsible for a visible message. Not every message shown to users has to exist as a literal string in the source code — it may come from translations, configuration, a database, or another service.
Search for a method call
Section titled “Search for a method call”Suppose we want to locate calls to a method named attempt:
git grep -n "attempt(" -- '*.php'Illustrative output:
app/Services/AuthService.php:28:if (!Auth::attempt($credentials)) {This is still a text search. It does not understand PHP method resolution or know whether every result calls the same runtime method.
What if nothing matches?
Section titled “What if nothing matches?”If no matching text is found, git grep normally prints no matching lines.
For example:
git grep "NonExistingService"may return to the command prompt without displaying results. This can mean:
- The text is not present in the searched tracked files.
- The letter case differs.
- The search was limited to the wrong directory or extension.
- The relevant file is untracked and therefore not searched by default.
- The code uses a different name.
An empty result is not proof that the idea does not exist anywhere in the complete project history — it only describes the tracked Working Tree files that were searched.
Does git grep search untracked files?
Section titled “Does git grep search untracked files?”By default, no. Suppose we create a new file:
app/Services/NewLoginService.phpIf Git does not track it yet, the normal command:
git grep "NewLoginService"does not search it by default.
git grep has additional modes that can widen the search, but they are
outside this beginner lesson.
git grep versus normal grep
Section titled “git grep versus normal grep”git grep
- Part of Git.
- Normally run inside a Git repository.
- Searches tracked files in the Working Tree by default.
- Understands Git pathspecs.
- Can be fast and convenient because Git already knows the tracked files.
Normal grep
- A general operating-system text-search tool.
- Not limited to Git repositories.
- Searches the files and paths the user gives it.
- Exact availability and behavior depend on the operating system and shell.
It would be inaccurate to claim that git grep is always faster than grep,
ripgrep, an IDE search, or every other search tool.
Practical mini-scenario
Section titled “Practical mini-scenario”The learner wants to investigate the Laravel login feature.
Step 1: Find every use of AuthService
Section titled “Step 1: Find every use of AuthService”git grep -n "AuthService"Step 2: Search only inside the tests
Section titled “Step 2: Search only inside the tests”git grep -n "AuthService" -- tests/Step 3: Search without caring about letter case
Section titled “Step 3: Search without caring about letter case”git grep -ni "authservice"Step 4: Display only matching filenames
Section titled “Step 4: Display only matching filenames”git grep -l "AuthService"Step 5: Find unfinished login work
Section titled “Step 5: Find unfinished login work”git grep -n "TODO" -- app/Each command answers a different question:
- Where is
AuthServiceused? - Which tests refer to it?
- Does a differently capitalized form exist?
- Which files are related to it?
- Where are unfinished tasks inside
app/?
Command summary
Section titled “Command summary”| Goal | Command |
|---|---|
| Search tracked file content | git grep "AuthService" |
| Show line numbers | git grep -n "AuthService" |
| Ignore letter case | git grep -i "authservice" |
| Combine line numbers and ignore case | git grep -ni "authservice" |
| Match at word boundaries | git grep -w "login" |
| Show only filenames | git grep -l "AuthService" |
| Search inside one directory | git grep -n "AuthService" -- app/ |
| Search only PHP files | git grep -n "AuthService" -- '*.php' |
| Find TODO comments | git grep -n "TODO" |
git grepanswers: “Which tracked files in my current Working Tree contain this text, and where does it appear?”