pre-commit
Git hooks framework for code quality.
Official WebsiteFeatures
Git HooksMulti-language SupportAuto UpdateCI IntegrationCustom Hooks
Installation
Homebrew
brew install pre-commitpip
pip install pre-commitWhy Use pre-commit?
pre-commit is a framework for managing Git hooks. It automatically runs code quality checks before committing, ensuring consistent code quality across the team.
Automatic Code Quality Checks
Automatically runs linters, formatters, and security scans before committing. Prevents problematic code from entering the repository.
Multi-Language Support
Unified management of tools for Python, JavaScript, Go, Rust, Ruby, Shell, and more languages.
Automatic Updates
Hook versions can be automatically updated. Always run checks with the latest tools.
CI Integration
Easy integration with CI services like GitHub Actions, GitLab CI, and CircleCI. Run the same checks locally and in CI.
Installation
Installation
# Install with pip (recommended)
pip install pre-commit
# macOS (Homebrew)
brew install pre-commit
# conda
conda install -c conda-forge pre-commit
# pipx (global install)
pipx install pre-commit
# Check version
pre-commit --versionBasic Usage
1. Create Configuration File
Create .pre-commit-config.yaml at the repository root.
.pre-commit-config.yaml
# .pre-commit-config.yaml (basic example)
repos:
# Common checks
- repo: https://github.com/pre-commit/pre-commit-hooks
rev: v4.5.0
hooks:
- id: trailing-whitespace # Remove trailing whitespace
- id: end-of-file-fixer # Add newline at end of file
- id: check-yaml # YAML syntax check
- id: check-json # JSON syntax check
- id: check-added-large-files # Prevent adding large files
- id: detect-private-key # Detect accidental private key commits
# For Python
- repo: https://github.com/psf/black
rev: 24.1.0
hooks:
- id: black # Code formatter
- repo: https://github.com/astral-sh/ruff-pre-commit
rev: v0.1.14
hooks:
- id: ruff # Linter
args: [--fix]
- id: ruff-format # Formatter2. Install Hooks
Hook Installation
# Install Git hooks
pre-commit install
# Also install commit-msg hook (for commit message validation)
pre-commit install --hook-type commit-msg
# Install all hook types
pre-commit install --install-hooks
# Verify installation
ls -la .git/hooks/3. Manual Execution
Manual Execution
# Run on all files
pre-commit run --all-files
# Run specific hook only
pre-commit run black --all-files
# Staged files only (same as on commit)
pre-commit run
# Run on specific files
pre-commit run --files src/main.py src/utils.pyPopular Hooks
JavaScript/TypeScript
JavaScript/TypeScript hooks
repos:
# ESLint
- repo: https://github.com/pre-commit/mirrors-eslint
rev: v8.56.0
hooks:
- id: eslint
files: \.[jt]sx?$
types: [file]
additional_dependencies:
- eslint@8.56.0
- eslint-config-prettier@9.1.0
- '@typescript-eslint/parser@6.19.0'
- '@typescript-eslint/eslint-plugin@6.19.0'
# Prettier
- repo: https://github.com/pre-commit/mirrors-prettier
rev: v3.1.0
hooks:
- id: prettier
types_or: [javascript, jsx, ts, tsx, json, yaml, markdown]Python
Python hooks
repos:
# Black (formatter)
- repo: https://github.com/psf/black
rev: 24.1.0
hooks:
- id: black
language_version: python3.11
# Ruff (fast linter/formatter)
- repo: https://github.com/astral-sh/ruff-pre-commit
rev: v0.1.14
hooks:
- id: ruff
args: [--fix, --exit-non-zero-on-fix]
# mypy (type checking)
- repo: https://github.com/pre-commit/mirrors-mypy
rev: v1.8.0
hooks:
- id: mypy
additional_dependencies: [types-requests]
# isort (organize imports)
- repo: https://github.com/pycqa/isort
rev: 5.13.2
hooks:
- id: isortSecurity & Secret Detection
Security Hooks
repos:
# Secret detection
- repo: https://github.com/Yelp/detect-secrets
rev: v1.4.0
hooks:
- id: detect-secrets
args: ['--baseline', '.secrets.baseline']
# Gitleaks (secret/API key detection)
- repo: https://github.com/gitleaks/gitleaks
rev: v8.18.1
hooks:
- id: gitleaks
# TruffleHog (secret scanning)
- repo: https://github.com/trufflesecurity/trufflehog
rev: v3.63.7
hooks:
- id: trufflehog
entry: bash -c 'trufflehog git file://. --only-verified --fail'Commit Messages
Commit Message Hooks
repos:
# Conventional Commits
- repo: https://github.com/compilerla/conventional-pre-commit
rev: v3.1.0
hooks:
- id: conventional-pre-commit
stages: [commit-msg]
args: [feat, fix, docs, style, refactor, perf, test, build, ci, chore]
# commitlint
- repo: https://github.com/alessandrojcm/commitlint-pre-commit-hook
rev: v9.11.0
hooks:
- id: commitlint
stages: [commit-msg]
additional_dependencies: ['@commitlint/config-conventional']Settings and Customization
Hook Configuration Options
Hook Configuration Options
repos:
- repo: https://github.com/pre-commit/pre-commit-hooks
rev: v4.5.0
hooks:
- id: check-added-large-files
args: ['--maxkb=500'] # Detect files over 500KB
exclude: ^docs/images/ # Exclude specific paths
- id: trailing-whitespace
files: \.(py|js|ts)$ # Target specific extensions only
exclude: ^tests/fixtures/ # Exclude test data
- id: check-yaml
args: ['--unsafe'] # Custom arguments
stages: [commit, push] # Specify stages to run
- repo: local
hooks:
- id: custom-script
name: Custom validation
entry: ./scripts/validate.sh
language: script
files: \.py$
pass_filenames: true # Pass filenames as arguments
always_run: false # Run only when changes existCreating Local Hooks
Local Hooks
repos:
- repo: local
hooks:
# Shell script
- id: check-todo
name: Check for TODO comments
entry: bash -c 'grep -rn "TODO" --include="*.py" && exit 1 || exit 0'
language: system
types: [python]
# Python script
- id: custom-python-check
name: Custom Python check
entry: python scripts/custom_check.py
language: python
files: \.py$
additional_dependencies: [click]
# Using Docker
- id: docker-lint
name: Docker lint
entry: docker run --rm -v "$PWD:/app" hadolint/hadolint hadolint
language: docker
files: DockerfileCI Integration
GitHub Actions
.github/workflows/pre-commit.yml
# .github/workflows/pre-commit.yml
name: pre-commit
on:
pull_request:
push:
branches: [main]
jobs:
pre-commit:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: actions/setup-python@v5
with:
python-version: '3.11'
- uses: pre-commit/action@v3.0.1GitLab CI
.gitlab-ci.yml
# .gitlab-ci.yml
pre-commit:
stage: test
image: python:3.11
variables:
PRE_COMMIT_HOME: $CI_PROJECT_DIR/.cache/pre-commit
cache:
paths:
- .cache/pre-commit
before_script:
- pip install pre-commit
script:
- pre-commit run --all-filesCommand List
| Command | Description |
|---|---|
pre-commit install | Install Git hooks |
pre-commit uninstall | Uninstall Git hooks |
pre-commit run | Run on staged files |
pre-commit run --all-files | Run on all files |
pre-commit autoupdate | Update hook versions to latest |
pre-commit clean | Clear cache |
pre-commit gc | Remove unused cache |
pre-commit sample-config | Output sample configuration file |
Tips
- *To skip hooks when committing, use
git commit --no-verify(emergency only) - *Regularly run
pre-commit autoupdateto keep hooks up to date - *Running the same hooks in CI catches cases that are skipped locally
- *Use
excludepatterns to exclude large files or specific paths - *Setting
fail_fast: truestops at the first error (useful for debugging) - *Document in README that all team members should run
pre-commit install
Official Resources
- Official Website: https://pre-commit.com/
- Available Hooks List: https://pre-commit.com/hooks.html
- GitHub: https://github.com/pre-commit/pre-commit