#3538·ripgrep

ignore: matched_path_or_any_parents doesn't skip excluded ancestors, and the doc-comment doesn't say so

Author: KaizenShogunCreated Sep 16, 2026Updated Sep 16, 2026

matched_path_or_any_parents returns as soon as the full path matches a rule — whitelist included — and only walks up to the parents when the path itself matched nothing (gitignore.rs:234). git never descends into an excluded directory, so a negation under one rescues nothing. Three rules files, git check-ignore --no-index (2.55.0) as the oracle, path asked for the way the API wants it (no trailing slash, is_dir passed separately):

rules path git matched_path_or_any_parents matched rg --files 14.1.1
dist/ + !*.pub dist/keep.pub ignored not ignored not ignored not listed ✓
.idea/ + !.idea/eclipseCodeFormatter.xml .idea/eclipseCodeFormatter.xml ignored not ignored not ignored not listed ✓
__tmp/ + !__tmp/keep __tmp/keep ignored not ignored not ignored not listed ✓

Scale, so it isn't three hand-made trees: over 9,852 (rules file, path) queries taken from the root .gitignore of 43 real repositories, matched_path_or_any_parents diverges from git on 63, and all 63 are that one shape and that one direction — git ignores, the crate doesn't. They're a strict subset of the 1,976 that plain matched gets wrong on the same corpus, so the parents walk is never worse, it just doesn't cover this. The walk isn't affected, as the last column shows.

I'm not asking for a behaviour change. Getting this right means knowing which directory the rules file governs and whether each ancestor is excluded, and that's the walk's job, not this method's. What I'd ask for is a line in the doc-comment, because #1715 and #2857 both end with the reporter adopting this method as the git-equivalent one and the limit isn't written anywhere.

Before filing I went looking for a consumer it actually bites, and I owe you the negative result: cargo isn't one. Five package trees, cargo package --list --allow-dirty inside a real repo with a commit — it excludes the re-included file in all five, matching git. (The control row, same trees with the negation removed, changes answer, so the ignore is genuinely being applied and the test isn't vacuous.) rustfmt does call it on bare paths (ignore_path.rs:27), but over rustfmt.toml's own ignore list rather than a .gitignore, where the divergence does no harm. So: a documented-behaviour gap I can measure, not a fire.

Corpus, adapter and the exact queries: https://github.com/KaizenShogun/gitignore-conformance