Open-Source Wikis

/

ripgrep

/

Features

/

Gitignore handling

BurntSushi/ripgrep

Gitignore handling

ripgrep's headline feature is automatic respect for .gitignore. This page covers exactly what that means, where the rules come from, and how the precedence works.

Files consulted

By default ripgrep loads ignore rules from, in priority order:

  1. --glob / --iglob flags on the command line. Highest priority. Whitelists or ignores override everything below. Source: crates/ignore/src/overrides.rs.
  2. The core.excludesFile global gitignore (whatever git config --get core.excludesFile returns; commonly ~/.config/git/ignore). Source: crates/ignore/src/gitignore.rs.
  3. .git/info/exclude in any ancestor git repository. Same matcher.
  4. .gitignore files in the file's directory and every ancestor up to the repository root. Same matcher.
  5. .ignore files. Same syntax as .gitignore but project-local and not committed by convention. Same matcher.
  6. .rgignore files. Same syntax but ripgrep-specific (e.g., for things you want to hide from rg but not from git).
  7. Hidden files. Files and directories whose name starts with . are skipped. Source: crates/ignore/src/walk.rs.
  8. Custom ignore files specified via --ignore-file PATH. Same matcher, given user-specified priority.

The precedence chain is implemented in crates/ignore/src/dir.rs (the per-directory IgnoreInner builder).

Negation in .gitignore

A leading ! in a gitignore pattern unignores a path that an earlier rule ignored. The matcher's Match<T> enum has three states:

  • Match::None — no rule matched.
  • Match::Ignore(...) — a non-negated rule matched; path is ignored.
  • Match::Whitelist(...) — a !-prefixed rule matched; path is explicitly allowed despite earlier rules.

Whichever rule matches last in the same gitignore file wins (gitignore semantics). Across files, the closer file (deeper in the tree) wins over the farther (closer to root). Across .gitignore vs. .ignore vs. .rgignore, the priority is the order listed above.

Disabling ignore rules

ripgrep exposes a ladder of "disable" flags. From least to most aggressive:

  • --no-ignore-vcs — disables .gitignore-style files but keeps .ignore and .rgignore.
  • --no-ignore — disables all per-directory ignore files.
  • --no-ignore-parent — only consults files in the search root, not ancestor directories.
  • --no-ignore-global — disables the global gitignore (core.excludesFile).
  • --no-ignore-dot — disables .ignore files but keeps .gitignore.
  • --hidden — also includes hidden files.
  • --no-require-git — uses gitignore matching even outside a git repo.
  • -uuu — shorthand for --no-ignore --hidden --binary.

The flags are defined in crates/core/flags/defs.rs; their effects are routed through WalkBuilder in crates/ignore/src/walk.rs.

Jujutsu (.jj) repositories

Since 15.0.0, ripgrep treats a directory containing a .jj/ subdirectory as if it were a git repository (FEATURE #2842). This means the gitignore stack still applies even when there's no .git/. Implemented in walk.rs's repo-root detection.

A 15.1.0 patch (BUG #3212) refines this: the .jj check is skipped when --no-ignore is in effect, since the user has already opted out of repo-relative ignore behaviour.

Parent-directory gitignores

When ripgrep is invoked inside a subtree of a larger repository (e.g., cd src && rg pattern), it walks up the directory tree to find ancestor .gitignore files. This is how rg correctly excludes target/ even if you run it from src/main.rs's directory.

Parent-directory gitignore handling has been a long source of subtle bugs. The 15.0.0 changelog cites BUG #829, #2731, #2747, #2770, #2778, #2836, #2933, #3067 — eight separate issues that were all rolled up into one unified fix.

Performance

The ignore stack is built once per directory and then re-used for every entry inside that directory. Matchers are globset::GlobSets, which can match a path against thousands of rules in roughly the same time as matching against a few. The cost of .gitignore evaluation in ripgrep is dominated by globset regex evaluation, not by ripgrep's traversal logic.

A 15.0.0 fix (BUG #2750) addressed a memory regression for very large gitignore files by changing how rules are interned.

Debugging

rg --debug prints "ignored by .gitignore" / "ignored by hidden" / "ignored by file size" for every excluded entry. This is the fastest way to find out which rule is hiding a file. See debugging.

Reference: file & function pointers

What Where
WalkBuilder configuration of ignore behaviour crates/ignore/src/walk.rs
Per-directory ignore stack assembly crates/ignore/src/dir.rs
.gitignore parsing and matching crates/ignore/src/gitignore.rs
--glob / --iglob overrides crates/ignore/src/overrides.rs
Global gitignore lookup crates/ignore/src/gitignore.rs::Gitignore::global
Repo-root detection (.git, .jj) crates/ignore/src/walk.rs
Three-state Match<T> crates/ignore/src/lib.rs
Default file types crates/ignore/src/default_types.rs
CLI flag definitions for --no-ignore-* crates/core/flags/defs.rs

For the package-level overview see packages: ignore.

Built by Factory AutoWiki from public repository content. It is a generated preview for codebase exploration, not source-maintained documentation.

Gitignore handling – ripgrep wiki | Factory