Pre-commit Hooks Setup Reference

Type: Software Reference Confidence: 0.92 Sources: 7 Verified: 2026-02-28 Freshness: 2026-02-28

TL;DR

Constraints

Quick Reference

CommandPurpose
pre-commit installInstall git hooks (once per clone)
pre-commit run --all-filesRun all hooks on entire repo
pre-commit run <hook-id>Run a single hook
pre-commit autoupdateUpdate all hook versions
SKIP=hook-id git commitSkip specific hook
git commit --no-verifySkip ALL hooks (emergency)
pre-commit cleanClear cached environments
pre-commit validate-configValidate YAML syntax
pre-commit try-repo <url>Test a hook repo

Decision Tree

START
├── Python? → ruff + mypy + pre-commit-hooks
├── JS/TS? → eslint + prettier via mirrors
├── Full-stack? → ruff + mypy + eslint + prettier
├── Go? → golangci-lint + gofmt
├── Need secrets detection? → gitleaks
└── DEFAULT → pre-commit-hooks (basics)

Step-by-Step Guide

1. Install pre-commit

[src1]

pip install pre-commit
# or: pipx install pre-commit
# or: brew install pre-commit

2. Create .pre-commit-config.yaml

[src1]

repos:
  - repo: https://github.com/pre-commit/pre-commit-hooks
    rev: v5.0.0
    hooks:
      - id: trailing-whitespace
      - id: end-of-file-fixer
      - id: check-yaml
      - id: check-json
      - id: check-added-large-files
        args: ['--maxkb=500']
      - id: check-merge-conflict
      - id: detect-private-key

3. Install git hooks

pre-commit install

4. Run on all files

pre-commit run --all-files

5. Add language-specific hooks

[src4]

  - repo: https://github.com/astral-sh/ruff-pre-commit
    rev: v0.9.6
    hooks:
      - id: ruff
        args: [--fix]
      - id: ruff-format

6. Keep hooks updated

pre-commit autoupdate

Code Examples

Python project: Ruff + MyPy

repos:
  - repo: https://github.com/pre-commit/pre-commit-hooks
    rev: v5.0.0
    hooks:
      - id: trailing-whitespace
      - id: end-of-file-fixer
      - id: check-yaml
      - id: check-added-large-files
      - id: detect-private-key
      - id: debug-statements
  - repo: https://github.com/astral-sh/ruff-pre-commit
    rev: v0.9.6
    hooks:
      - id: ruff
        args: [--fix, --exit-non-zero-on-fix]
      - id: ruff-format
  - repo: https://github.com/pre-commit/mirrors-mypy
    rev: v1.14.1
    hooks:
      - id: mypy
        additional_dependencies: [types-requests, types-PyYAML]

JavaScript/TypeScript: ESLint + Prettier

repos:
  - repo: https://github.com/pre-commit/pre-commit-hooks
    rev: v5.0.0
    hooks:
      - id: trailing-whitespace
      - id: end-of-file-fixer
      - id: check-json
  - repo: https://github.com/pre-commit/mirrors-eslint
    rev: v9.20.0
    hooks:
      - id: eslint
        files: \.(js|jsx|ts|tsx)$
        additional_dependencies:
          - [email protected]
          - [email protected]
  - repo: https://github.com/pre-commit/mirrors-prettier
    rev: v4.0.0-alpha.8
    hooks:
      - id: prettier
        types_or: [javascript, jsx, ts, tsx, css, json, yaml, markdown]

Full-stack + security

repos:
  - repo: https://github.com/pre-commit/pre-commit-hooks
    rev: v5.0.0
    hooks:
      - id: trailing-whitespace
      - id: end-of-file-fixer
      - id: check-merge-conflict
      - id: no-commit-to-branch
        args: ['--branch', 'main']
  - repo: https://github.com/astral-sh/ruff-pre-commit
    rev: v0.9.6
    hooks:
      - id: ruff
        files: ^backend/
      - id: ruff-format
        files: ^backend/
  - repo: https://github.com/pre-commit/mirrors-prettier
    rev: v4.0.0-alpha.8
    hooks:
      - id: prettier
        files: ^frontend/
  - repo: https://github.com/gitleaks/gitleaks
    rev: v8.23.3
    hooks:
      - id: gitleaks

Anti-Patterns

Wrong: Using branch names for rev

# ❌ BAD — non-reproducible
rev: main

Correct: Pin to version tags

# ✅ GOOD — pinned, reproducible
rev: v0.9.6

Wrong: Running heavy checks on all files

# ❌ BAD — 30+ seconds per commit
- id: mypy
  pass_filenames: false  # Checks ALL files

Correct: Check only staged files

# ✅ GOOD — only staged files (default)
- id: mypy
  # pass_filenames: true is the default

Wrong: Not documenting installation

# ❌ BAD — new contributors don't know hooks exist

Correct: Add to setup script

# ✅ GOOD — in Makefile
setup:
	pip install pre-commit
	pre-commit install

Common Pitfalls

Diagnostic Commands

# Version
pre-commit --version

# Validate config
pre-commit validate-config

# Run all hooks
pre-commit run --all-files

# Run specific hook
pre-commit run ruff --all-files

# Update hooks
pre-commit autoupdate

# Clear cache
pre-commit clean

# Test a repo
pre-commit try-repo https://github.com/astral-sh/ruff-pre-commit --all-files

Version History & Compatibility

VersionStatusBreaking ChangesMigration Notes
pre-commit 4.xCurrentPython 3.8 droppedEnsure Python 3.9+
pre-commit 3.xMaintenanceLast for Python 3.8
RuffCurrentReplaces black, isort, flake8ruff + ruff-format

When to Use / When Not to Use

Use WhenDon't Use WhenUse Instead
Any git repo with 2+ contributorsSolo prototypeManual checks
Multi-language projectNode.js-only (JS ecosystem)Husky + lint-staged
Need consistent qualityCI-only checks sufficientGitHub Actions linting

Important Caveats

Related Units