Skip to content

fix(linter): detect git repo at runtime to fix .gitignore bleed across nested repos#20952

Closed
fabb wants to merge 3 commits into
oxc-project:mainfrom
fabb:fix/nested_git_repos2
Closed

fix(linter): detect git repo at runtime to fix .gitignore bleed across nested repos#20952
fabb wants to merge 3 commits into
oxc-project:mainfrom
fabb:fix/nested_git_repos2

Conversation

@fabb

@fabb fabb commented Apr 2, 2026

Copy link
Copy Markdown

Alternative approach: #20951 uses a simpler require_git(true) but reverts #17375.

Summary

Detects at runtime whether the walked paths are inside a git repository and sets require_git accordingly — true inside a git repo (correct git-boundary behaviour), false outside (preserving the behaviour from #17375 where .gitignore rules apply even without a .git ancestor).

The problem: require_git(false) (introduced in #17375) makes the ignore crate read .gitignore files from directories above the git root, which differs from standard git behaviour. This causes a concrete bug in nested git repositories: parent_repo/.gitignore incorrectly filters files inside parent_repo/child_repo/, which has its own .git.

Why require_git(true) fixes it: The ignore crate already implements correct git-boundary logic via a saw_git flag in matched_ignore. When iterating parent directories from innermost to outermost, saw_git becomes true at the innermost .git boundary, preventing gitignore rules from any outer repository from applying. require_git(true) activates this standard git behaviour.

Trade-off: None — the runtime detection preserves #17375 behaviour for non-git directories while fixing the nested-repo bug for git repos.

Fixes #17805
Fixes #17510
Supersedes #17813

…s nested repos

Detects at runtime whether the walked paths are inside a git repository
and sets `require_git` accordingly — `true` inside a git repo (activating
correct git-boundary behaviour), `false` outside (preserving the behaviour
introduced in oxc-project#17375 where `.gitignore` rules apply even without a `.git`
ancestor).

**The problem:** `require_git(false)` (introduced in oxc-project#17375) makes the
`ignore` crate read `.gitignore` files from directories *above* the git
root, which differs from standard git behaviour. This causes a concrete
bug in nested git repositories: `parent_repo/.gitignore` incorrectly
filters files inside `parent_repo/child_repo/`, which has its own `.git`.

**Why `require_git(true)` fixes it:** The `ignore` crate already
implements correct git-boundary logic via a `saw_git` flag in
`matched_ignore`. When iterating parent directories from innermost to
outermost, `saw_git` becomes `true` at the innermost `.git` boundary,
preventing gitignore rules from any outer repository from applying.
`require_git(true)` activates this standard git behaviour.

**Trade-off:** None — the dynamic detection preserves oxc-project#17375 behaviour
for non-git directories while fixing the nested-repo bug for git repos.
@fabb
fabb force-pushed the fix/nested_git_repos2 branch from cf575e6 to 839bf37 Compare April 2, 2026 05:37
graphite-app Bot pushed a commit that referenced this pull request May 1, 2026
This regressed in oxlint v1.36.0 (fec2863)

This is caused by the walker configuring `ignore` with `.require_git(false)`, which makes `.gitignore` files from parent directories above the current repository apply to the walk. That differs from Git behavior, where `.gitignore` lookup stops at the working tree root.

Here is how we handle it:

- detect whether all walk roots are inside a Git/JJ repository boundary
- enable `require_git(true)` for repository walks so parent `.gitignore` files above the repo boundary are ignored
- keep `require_git(false)` for non-repository walks so local `.gitignore` files still work outside Git repos
- add regression coverage for nested repositories, worktree-style `.git` files, and subdirectory walks inside a repo

Here is how the `ignore` crate checks for git directories:

- when `require_git(true)` is enabled, it records whether each directory has a `.git` or `.jj` entry
- while matching `.gitignore` rules, it applies parent gitignore matchers only until it has seen that repository boundary
- `.git` files are handled as boundaries too, which covers Git worktrees

Fixes #17510.
Fixes #17805.
Fixes #19902.
Closes #21727.
Closes #17513.
Closes #17813.
Closes #20951.
Closes #20952.
@graphite-app graphite-app Bot closed this in #22033 May 1, 2026
@camc314

camc314 commented May 2, 2026

Copy link
Copy Markdown
Contributor

massive apologies for the delay on this, but thank you for submitting this PR!

I think i've fixed this in a slightly more ideal way, in #22033, that maintains the previous behaviour, while allowiing .gitignores in non-git initialized directories.

The fix should be released on Monday (May 4th) (or possibly tuesday due to the holiday) - please try it and let me know!

Thanks!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

A-cli Area - CLI A-formatter Area - Formatter A-linter Area - Linter C-bug Category - Bug

Projects

None yet

Development

Successfully merging this pull request may close these issues.

linter: home directory gitignore breaks oxlint npx oxlint . checks 26 files with Version: 1.31.0 but 0 files with Version: 1.36.0

2 participants