# How to Debug Why a File Isn't Being Ignored by Git: A Complete Guide

> Debug why a file isnt ignored by Git. Use git check-ignore -v to find the exact rule or missing rule. Get your .gitignore working perfectly.

- Repository: [GitHub/gitignore](https://github.com/github/gitignore)
- Tags: how-to-guide
- Published: 2026-02-24

---

**Use `git check-ignore -v <path>` to identify exactly which rule applies to a file, or why no rule matches at all.**

When a file refuses to be ignored despite an entry in your `.gitignore`, the issue usually stems from rule precedence or pattern syntax errors. The `github/gitignore` repository provides the canonical templates that most projects use as a foundation for their ignore rules, making it the authoritative reference for understanding how these patterns work. Understanding how Git processes these rules—and how to debug them—is essential for maintaining clean repositories.

## How Git Processes gitignore Rules (Precedence Matters)

Git reads `.gitignore` files in a specific hierarchy, applying the **first matching rule** it encounters. The order of precedence is critical: Git starts with the `.gitignore` in the current directory, moves up through parent directories, and finally checks the global ignore file configured in your Git settings.

The first rule that matches wins. However, a later negation pattern using `!` can re-include a path that a previous rule excluded. According to the `github/gitignore` source structure documented in [`README.md`](https://github.com/github/gitignore/blob/main/README.md), templates are designed to be copied into projects where they become part of this hierarchical decision tree.

## Critical Pattern Syntax from github/gitignore Templates

The `github/gitignore` repository demonstrates standard pattern syntax that determines whether a rule matches your file:

- **Wildcards**: Patterns like `*.log` ignore any file ending with `.log` anywhere in the tree
- **Directory anchors**: A leading slash like `/build/` matches only the `build` directory at the repository root
- **Negation**: Prefixing with `!` (e.g., `!important.txt`) re-includes files that previous patterns excluded
- **Directory-only**: Adding a trailing slash like `env/` restricts the match to directories only

For example, the `Python.gitignore` template contains specific rules for virtual environments (`env/`, `venv/`, `.venv/`) and cache directories (`__pycache__/`).

## Common Pitfalls Preventing Files from Being Ignored

Several syntax nuances in the `github/gitignore` templates commonly cause confusion when debugging why a file isn't being ignored:

**Negated Patterns (`!`)**

If a later rule un-ignores a path (e.g., `!.env.example` after `.env`), Git tracks the file regardless of earlier exclusion rules.

**Pathspec Scope**

Patterns are relative to the `.gitignore` file containing them. A rule like `build/` in the root ignores only the root-level `build/` directory, not `submodule/build/` unless that submodule has its own matching rule.

**Trailing Slash vs. No Slash**

`temp` matches both files and directories named `temp`, while `temp/` matches only directories.

**Whitespace Errors**

Blank lines and lines beginning with `#` are ignored. Accidentally inserting a space before a pattern (e.g., `" *.py"` with a leading space) treats the space as a literal character, causing the pattern to fail.

## Debugging with `git check-ignore`

Git provides a built-in command to diagnose exactly which rule affects a specific path. This is the primary tool for debugging why a file isn't being ignored.

```bash
git check-ignore -v path/to/file

```

The `-v` flag outputs the source file, line number, and matching pattern. If the command returns nothing, no ignore rule matches the file.

**Example output:**

```bash
$ git check-ignore -v src/__pycache__/module.cpython-38.pyc
.gitignore:2:__pycache__/    src/__pycache__/module.cpython-38.pyc

```

This indicates that line 2 of the repository's `.gitignore` (`__pycache__/`) is responsible for ignoring the file.

**Additional debugging options:**

```bash

# Show all ignore rules affecting a file including parent directories

git check-ignore -v -n path/to/file

# Test a pattern without modifying files

git check-ignore -v --no-index -p 'logs/*.log' src/logs/debug.log

# Check why .env isn't ignored (may point to Python.gitignore line 51)

git check-ignore -v .env

```

## Fixing gitignore Issues

Once you identify the conflicting rule using `git check-ignore`, resolve the issue by:

1. **Verifying pattern syntax**: Ensure wildcards, leading slashes, and trailing slashes match your intended path structure
2. **Checking for negation**: Look for subsequent `!` rules that re-include the path
3. **Inspecting parent directories**: If the rule lives in a parent directory's `.gitignore`, edit that file or add a more specific rule in your repository root
4. **Reviewing global ignores**: Check your global configuration with `git config --get core.excludesfile` and examine files like `Global/JetBrains.gitignore` or `Global/VisualStudioCode.gitignore` referenced in the `github/gitignore` repository

## Summary

- Git applies `.gitignore` rules from top to bottom, with the first match winning, though later `!` patterns can re-include files
- Use `git check-ignore -v <path>` to identify exactly which rule ignores a file or confirm no rule matches
- Pattern syntax details like leading slashes (`/build/`), trailing slashes (`env/`), and negation (`!`) determine matching behavior
- Files in parent directories or global ignore files (referenced in templates like `Global/JetBrains.gitignore`) may override local rules
- Whitespace and scope issues are common causes of rules failing to match unexpectedly

## Frequently Asked Questions

### Why is my `.gitignore` file not ignoring files I've already committed?

Git ignores only untracked files. If a file was already committed before you added the ignore rule, Git continues tracking it. Run `git rm --cached <file>` to untrack the file while preserving it in your working directory, then commit the change.

### How do I check which gitignore rule is blocking a file from being tracked?

Run `git check-ignore -v path/to/file`. This outputs the specific `.gitignore` file, line number, and pattern that matches the path. If the command produces no output, no ignore rule currently applies to that file.

### Can a global gitignore file override my project's `.gitignore`?

No. Git processes rules from the local `.gitignore` upward through parent directories, checking the global ignore file last. However, a negation pattern (`!`) in a parent directory or global file can re-include a path that your local file ignored, effectively overriding the exclusion.

### Why does `build/` in my root `.gitignore` not ignore a `build` folder in a subdirectory?

Patterns without a leading slash match from the `.gitignore` file's location downward. If `build/` is in the root `.gitignore`, it should ignore all `build` directories recursively. However, if a parent directory's `.gitignore` or a global file contains a negation pattern like `!build/`, or if the file is already tracked, the ignore rule appears to fail. Use `git check-ignore -v` to verify which rule applies.