# Searching code from the command line: ripgrep, ugrep or git grep, and which files each one sees

For assistants asked to find text in a code tree, this feature compares the three recorded search tools on the same six authored files. headlesson ran ripgrep 15.1.0, ugrep 7.8.5 and git grep 2.50.1 (Apple Git-155) on macOS: once the set of files to search was made the same, the matching file, line and text agreed, but each tool picks a different default set of files and prints a different machine format, and git grep exited 128 for a bad pattern while ripgrep and ugrep exited 2. It is a small sample, not a speed or full compatibility comparison.

Published 2026-10-14, updated 2026-10-14. Editorial article by the headlesson operator, written from the catalog records it cites. Test results in it are the operator's own observations, not vendor claims. Each cited record keeps its own source; the article's editorial source does not stand in for them.

## Which files get searched by default

- The six authored files were .gitignore, .hidden.py, src/main.rs, src/util.py, build/out.txt and app.log, with .gitignore listing the last two. ripgrep (rg) (`app:ripgrep`), ugrep (`app:ugrep`) and git grep (Git subcommand) (`app:git-grep`) were given byte-identical copies.
- ripgrep (rg) (`app:ripgrep`) skips ignored and hidden files by default, but applies .gitignore only inside a Git repository; in a separate authored tree used in its 2026-10-11 test, a copy without .git returned matches from ignored files, so --no-require-git was needed.
- ugrep (`app:ugrep`) uses .gitignore only when --ignore-files is given, and --hidden adds hidden files.
- git grep (Git subcommand) (`app:git-grep`) searches tracked files by default, including a tracked hidden file: 2 matches here. --untracked gave 3, --untracked --no-exclude-standard gave 5, and --no-index --exclude-standard gave 3.
- Editorial advice, not tested beyond these files: state the directory and the hidden and ignore rules explicitly with ripgrep (rg) (`app:ripgrep`), ugrep (`app:ugrep`) or git grep (Git subcommand) (`app:git-grep`) rather than relying on defaults, and check whether ignored or hidden files such as .env may be read before widening the search.

## Observed in the tests

- With the hidden and ignore rules set to match, ripgrep (rg) (`app:ripgrep`) and git grep (Git subcommand) (`app:git-grep`) returned the same file, line number and text for the 3-match and 5-match cases, and ripgrep (rg) (`app:ripgrep`) and ugrep (`app:ugrep`) agreed on the ordinary (2) and hidden (3) cases. Output order was not compared.
- Machine output differs: ripgrep (rg) (`app:ripgrep`) --json prints JSON Lines events, ugrep (`app:ugrep`) --json prints one JSON array of files with nested matches, and git grep (Git subcommand) (`app:git-grep`) was read through -n -z, which separates file, line number and text with NUL bytes and is not JSON. The sets were compared after decoding.
- No match exited 1 with ripgrep (rg) (`app:ripgrep`), ugrep (`app:ugrep`) and git grep (Git subcommand) (`app:git-grep`). An invalid pattern "(" exited 2 with ripgrep (rg) (`app:ripgrep`) and ugrep (`app:ugrep`) but 128 with git grep (Git subcommand) (`app:git-grep`), so a caller cannot treat every non-zero exit as "no match".
- Each lesson passed all of its steps: ripgrep (rg) (`app:ripgrep`) with the Homebrew build already installed (2026-10-11), ugrep (`app:ugrep`) built from pinned source with optional PCRE2, Boost Regex and compression libraries turned off, and git grep (Git subcommand) (`app:git-grep`) with the Git that ships with macOS and every command isolated from the user's Git configuration with env -i and configuration controls.

## What was not tested

The comparison of ripgrep (rg) (`app:ripgrep`), ugrep (`app:ugrep`) and git grep (Git subcommand) (`app:git-grep`) used six small files. Binary files, Unicode, multiline matches, file names containing newlines, symlinks, full regex compatibility, ugrep's TUI and compressed-file search, speed and memory were not tested; ugrep (`app:ugrep`) was not rerun for the git grep comparison, only its saved inputs were checked byte for byte. headlesson_get with sections ["lesson","gotchas"] on each ID gives the exact commands, versions and failure conditions.


## Records cited

Each line gives the record, its public page if there is one, and where its name comes from.

- ripgrep (rg) — `app:ripgrep` (no public page yet; available over MCP); source: [https://github.com/BurntSushi/ripgrep/blob/master/README.md](https://github.com/BurntSushi/ripgrep/blob/master/README.md) (checked 2026-10-11, primary, official)
- ugrep — `app:ugrep` (no public page yet; available over MCP); source: [https://github.com/Genivia/ugrep/blob/v7.8.5/README.md](https://github.com/Genivia/ugrep/blob/v7.8.5/README.md) (checked 2026-10-14, primary, official)
- git grep (Git subcommand) — `app:git-grep` (no public page yet; available over MCP); source: [https://github.com/git/git/blob/v2.50.1/Documentation/git-grep.adoc](https://github.com/git/git/blob/v2.50.1/Documentation/git-grep.adoc) (checked 2026-10-14, primary, official)

## Article source

headlesson editorial judgement (checked 2026-10-14, inferred, editorial).

## Retrieve over MCP

`headlesson_get id="feature:code-search"` on https://mcp.headlesson.com/mcp

Page updated: 2026-10-14 (the date its content last changed).

要約（日本語）: headlesson の運営が、カタログの記録（試用の結果と注意点）だけから書いた使い分けの特集。試用の結果は記載の版・日付での運営の観察で、精度や安全性の保証ではない。
