Skip to content

Fix gitignore negation in child files not overriding parent/global rules#300613

Open
Dmitriusan wants to merge 1 commit intomicrosoft:mainfrom
Dmitriusan:fix/gitignore-negation-parent-override
Open

Fix gitignore negation in child files not overriding parent/global rules#300613
Dmitriusan wants to merge 1 commit intomicrosoft:mainfrom
Dmitriusan:fix/gitignore-negation-parent-override

Conversation

@Dmitriusan
Copy link

@Dmitriusan Dmitriusan commented Mar 11, 2026

Problem

When explorer.excludeGitIgnore is enabled, negation patterns (e.g., !.myconfig/) in a project's .gitignore do not override matching positive patterns from parent or global gitignore files.

Reproduction:

  1. Global ~/.gitignore_global contains .myconfig
  2. Project .gitignore contains !.myconfig/
  3. Files inside .myconfig/ are tracked by git and git check-ignore correctly reports them as not ignored
  4. VS Code's file explorer still dims/hides these files

Root Cause

In IgnoreFile.parseIgnoreFile(), the isPathIgnored function only uses negation patterns to counteract positive patterns within the same file. When the current file has no positive pattern for a path, it falls through to the parent's isPathIgnored() without checking whether the current file has a negation that should override the parent.

In git's actual behavior, the last matching rule wins, and rules in more-specific .gitignore files (child directories) take precedence over less-specific ones (parent directories, global gitignore).

Fix

Before delegating to the parent, check if the current file has a negation pattern that matches the path. If so, return false (not ignored) without consulting the parent. This correctly implements git's precedence semantics.

Testing

Added two test cases:

  • Child negation overrides parent ignore for directories — simulates a global ignore pattern being overridden by a project-level negation
  • Child negation overrides parent ignore for files — simulates *.log / !important.log across parent/child

Relates to #156077

@Dmitriusan
Copy link
Author

@microsoft-github-policy-service agree

When a child .gitignore contains a negation pattern (e.g., `!.claude/`),
it should override a matching positive pattern from a parent or global
.gitignore (e.g., `.claude`). Previously, negation patterns in the
current file were only checked against the current file's own positive
patterns. If the current file had no matching positive pattern, the
negation was ignored and the parent's positive pattern took effect.

This fix adds explicit checks: if a negation pattern in the current
file matches the path, return false (not ignored) without delegating
to the parent. This matches git's actual behavior where the last
matching rule wins and child gitignore files take precedence over
parent/global ones.

Fixes microsoft#156077
@Dmitriusan Dmitriusan force-pushed the fix/gitignore-negation-parent-override branch from 5b56791 to d131c2c Compare March 11, 2026 01:13
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants