Skip to content
Latchkey

pre-commit files and exclude: Path Filtering

files and exclude are regular expressions that include or exclude paths from a hook.

pre-commit matches files against these patterns to decide what each hook sees. They are Python regexes, not globs, and that trips people up.

What it does

A top-level files/exclude filters every hook; a per-hook files/exclude filters that one hook. A path runs through a hook only if it matches files (default: everything) and does not match exclude. The patterns are anchored-search Python regular expressions.

Common usage

.pre-commit-config.yaml
exclude: '^(vendor/|third_party/|.*\.min\.js$)'
repos:
  - repo: https://github.com/psf/black
    rev: 24.4.2
    hooks:
      - id: black
        files: '^src/'
        exclude: '^src/generated/'

Keys

KeyWhat it does
filesRegex of paths to include (default: all)
excludeRegex of paths to skip
exclude_typesSkip files of a detected type
types / types_orRestrict to detected file types
^ and $Anchor the pattern; multiline excludes use ( | ) groups

In CI

Because patterns are regexes, escape dots and remember these are not globs: ^.*\.lock$ not *.lock. To exclude many directories, use an alternation with ^( ... ) and the YAML block-scalar syntax for long lists. The meta hook check-useless-excludes flags exclude patterns that match nothing.

Common errors in CI

A hook that "still runs on a file you excluded" almost always has a glob where a regex was expected; convert *.min.js to .*\.min\.js$. "check-useless-excludes" failing means an exclude pattern no longer matches any file. An unescaped regex metacharacter can raise a config error or silently match too much.

Related guides

Run this faster and cheaper on Latchkey managed runners. Start free →