.gitignore Syntax & Pattern Matching Guide
Git pattern matching is based on Unix globbing with specialized rules for directories, recursive filepaths, and negation. Understanding these rules ensures your project excludes unintended files without inadvertently ignoring essential source code.
1. Basic Formatting: Comments & Blank Lines
Every line in a .gitignore file represents an independent pattern, with two core exceptions:
- Blank lines are ignored and serve as visual separators to keep files readable.
- Lines beginning with
#are comments and have no effect on file tracking. - Trailing spaces are ignored unless escaped with a backslash (
\).
# Ignore Python compiled bytecode __pycache__/ *.py[cod] # Ignore local secret configurations .env .env.local
2. Wildcard Globbing (*, ?, [ ])
Git supports standard shell globbing wildcards within a single directory level:
* (Asterisk)Matches zero or more characters in a single path segment. *.log matches error.log, but not nested/error.log if anchored.
? (Question Mark)Matches exactly one single character. test?.js matches test1.js and testA.js, but not test12.js.
[abc] (Range)Matches any single character within the bracket set. *.[oa] matches object files ending in .o or archive files in .a.
3. Leading, Trailing, and Middle Slashes
The placement of forward slashes (/) completely alters how Git interprets patterns:
logs/Forces the pattern to match only directories. It will ignore a directory named logs/, but will not ignore a regular file named logs.
/config.jsonAnchors the match to the root level where .gitignore resides. It ignores /config.json, but allows /packages/app/config.json to remain tracked.
docs/*.htmlA slash anywhere in the middle also anchors relative to the directory containing the .gitignore file.
4. Recursive Double Asterisk (**)
The double asterisk matches across multiple directory hierarchies:
**/cache: Matches any folder or file namedcacheanywhere in the repository (cache,src/cache,a/b/c/cache).logs/**: Matches all files and subdirectories inside thelogs/directory, no matter how deeply nested.a/**/b: Matchesa/b,a/x/b,a/x/y/b, etc.
5. Negation (!) and the Critical Directory Trap
An exclamation mark (!) negates a rule, telling Git to track a file even if an earlier pattern would have ignored it.
For performance reasons, Git stops traversing directories as soon as a directory is ignored. If a parent directory is excluded with build/, Git will never re-include a file inside it using !build/important.txt!
To properly un-ignore a file inside an ignored folder, you must un-ignore the folder structure while ignoring contents:
# INCORRECT: Will NOT work because parent directory is skipped node_modules/ !node_modules/my-local-package # CORRECT: Ignore contents of directory, then whitelist the specific target node_modules/* !node_modules/my-local-package/
Generate a Conflict-Free .gitignore
Don't wrestle with manual globbing conflicts. DotGitIgnore combines verified templates for your languages, frameworks, and developer tools deterministically.