Appearance
Exclude pattern syntax
Exclude patterns are globs, matched against each file's path relative to the repository root — apps/server/src/index.ts, never a leading ./ or /.
Anchoring
This is the rule that catches people out:
| Pattern contains | Matched against | Example |
|---|---|---|
No / | The file name only, at any depth | *.snap matches src/__snapshots__/Button.snap |
A / | The full path from the repository root | src/generated/** matches only under that exact directory |
So a directory that can appear anywhere needs a **/ prefix: **/generated/**, not generated/**.
Wildcards
| Token | Matches | Example |
|---|---|---|
* | Any characters except / | *.min.js |
** | Any number of directories | **/vendor/** |
? | Exactly one character | v?.config.ts |
{a,b} | Any of the alternatives | *.{png,jpg,svg} |
[abc] | One character from the set | chunk-[0-9].js |
Dotfiles are matched like any other file: * covers .eslintrc, and **/.github/** works as written.
Recipes
| Goal | Pattern |
|---|---|
| Snapshots anywhere | *.snap |
| Every test file | **/*.{test,spec}.* |
| One directory at the root | vendor/** |
| The same directory at any depth | **/vendor/** |
| Database migrations | **/migrations/** |
| Generated API clients | **/api/generated/** |
| Images and fonts | *.{png,jpg,jpeg,gif,svg,woff,woff2} |
| All documentation | *.md |
| One specific file | packages/db/src/schema/index.ts |
Pitfalls
Do not use negation. A pattern starting with ! means "everything except this", and since a file is skipped as soon as any pattern matches it, !*.md excludes your entire codebase apart from Markdown. To bring a file back, delete the pattern that catches it — the list holds every exclusion there is.
dist/** is not enough for a monorepo — it only matches at the root. Use **/dist/**, which is in the starting list anyway.
Invalid globs are rejected on the spot. A pattern the matcher cannot parse — an unclosed [, say — is refused with Pattern is not a valid glob. and never reaches your list.
A trailing / does nothing. Write **/fixtures/**, not **/fixtures/.
Patterns are not regular expressions. .* matches a literal dot followed by anything, not "any characters".
Verifying
Open the review detail for a pull request that touches the file and select it in the Skipped group. A file an exclusion caught is labelled excluded, and the pane on the right names the exact pattern that matched:
text
Excluded by pattern: **/migrations/**A file labelled too large was skipped because GitHub provided no diff for it — a binary or an oversized file — and no pattern was involved.