Pre-commit hooks are automated scripts that run before each Git commit, catching code quality issues, formatting problems, and security risks early before code reaches version control.
What Are Pre-commit Hooks?
- Automation: Run checks automatically on every commit
- Prevention: Stop bad code from entering repository
- Enforcement: Maintain standards across team
- Speed: Catch issues before code review (save time!)
- Consistency: Ensure everyone follows same rules
How Pre-commit Works
1. Developer runs git commit
2. Pre-commit hooks run on staged files
3. Hooks check formatting, lint, tests, security
4. If issues found, commit blocked, fixes suggested
5. Developer fixes and commits again
Installation & Setup
``bash
# Install pre-commit
pip install pre-commit
# Create .pre-commit-config.yaml
cat > .pre-commit-config.yaml << EOF
repos:
- repo: https://github.com/pre-commit/pre-commit-hooks
rev: v4.5.0
hooks:
- id: trailing-whitespace
- id: end-of-file-fixer
- id: check-yaml
- id: check-json
EOF
# Install hooks into git
pre-commit install
# Now hooks run automatically on every commit!
`
Popular Hook Categories
Python Code Quality:
`yaml
repos:
# Black formatter
- repo: https://github.com/psf/black
rev: 23.12.0
hooks:
- id: black
language_version: python3
# Ruff linter (fast, comprehensive)
- repo: https://github.com/astral-sh/ruff-pre-commit
rev: v0.1.9
hooks:
- id: ruff
args: [--fix]
# isort import sorting
- repo: https://github.com/PyCQA/isort
rev: 5.13.0
hooks:
- id: isort
# mypy type checker
- repo: https://github.com/pre-commit/mirrors-mypy
rev: v1.7.1
hooks:
- id: mypy
`
JavaScript/Web:
`yaml
# ESLint
- repo: https://github.com/pre-commit/mirrors-eslint
rev: v8.56.0
hooks:
- id: eslint
types: [javascript]
# Prettier formatter
- repo: https://github.com/pre-commit/mirrors-prettier
rev: v3.1.0
hooks:
- id: prettier
types: [javascript, css, markdown]
`
Security & Secrets:
`yaml
# Detect secrets
- repo: https://github.com/Yelp/detect-secrets
rev: v1.4.0
hooks:
- id: detect-secrets
# Bandit for security issues
- repo: https://github.com/PyCQA/bandit
rev: 1.7.5
hooks:
- id: bandit
`
General/File Checks:
`yaml`
- repo: https://github.com/pre-commit/pre-commit-hooks
rev: v4.5.0
hooks:
- id: trailing-whitespace
- id: end-of-file-fixer
- id: check-yaml
- id: check-json
- id: check-merge-conflict
- id: check-docstring-first
- id: debug-statements
- id: mixed-line-ending
- id: detect-private-key
Usage Examples
Basic Commands:
`bash
# Hooks run automatically on commit
git commit -m "Add feature"
# Skip hooks (not recommended!)
git commit --no-verify
# Run on all files
pre-commit run --all-files
# Run specific hook
pre-commit run black --all-files
# Update hooks
pre-commit autoupdate
# Clean up
pre-commit clean
`
Complete Configuration Example
`yaml
# .pre-commit-config.yaml
repos:
- repo: https://github.com/pre-commit/pre-commit-hooks
rev: v4.5.0
hooks:
- id: trailing-whitespace
- id: end-of-file-fixer
- id: check-yaml
- id: check-json
- id: mixed-line-ending
- repo: https://github.com/psf/black
rev: 23.12.0
hooks:
- id: black
- repo: https://github.com/astral-sh/ruff-pre-commit
rev: v0.1.9
hooks:
- id: ruff
args: [--fix]
- repo: https://github.com/pre-commit/mirrors-mypy
rev: v1.7.1
hooks:
- id: mypy
additional_dependencies: [types-all]
- repo: https://github.com/Yelp/detect-secrets
rev: v1.4.0
hooks:
- id: detect-secrets
`
Advantages
✅ Catch issues early: Before code review stage
✅ Consistent style: Automatic formatting enforcement
✅ Prevent secrets: Don't accidentally commit passwords
✅ Save time: Automate tedious checks
✅ Team alignment: Everyone uses same tools
✅ Faster reviews: PR reviewers focus on logic, not style
✅ Quality gates: Never commit broken code
Disadvantages
❌ Initial setup: Takes time to configure
❌ Performance: Can slow down commits if inefficient
❌ Learning curve: Teams must understand workflow
❌ Maintenance: Keep hooks updated with project needs
Best Practices
1. Keep hooks fast: <10 seconds total (use --no-verify sparingly)pre-commit autoupdate
2. Auto-fix when possible: Format, import sort automatically
3. Run on CI/CD too: Backup enforcement in pipeline
4. Document in README: Tell team why hooks exist
5. Update regularly: quarterly`
6. Exclude files: Some files shouldn't be checkedyaml`
exclude: ^(venv/|build/|migrations/)
7. Make skip easy for urgent fixes: Via documentation, not encouragement
Real-World Workflow
`bash
# Project setup
git clone project
cd project
pip install pre-commit
pre-commit install
# Now normal development
git add myfile.py
git commit -m "Add feature"
# Pre-commit runs automatically:
# - Black formats code
# - Ruff finds issues
# - mypy checks types
# - Detects secrets
# If issues found:
# Fix automatically (Black)
# Fix manually (Ruff warnings)
# git add fixed files
# git commit again (now passes!)
``
Comparison: Pre-commit vs CI/CD
| Aspect | Pre-commit | CI/CD |
|--------|-----------|-------|
| When | Before commit | After push |
| Cost | Fast feedback | Waiting, PR rejection |
| Scope | Staged files | Whole repo |
| Use | Developer machine | Server |
| Best For | Fast feedback | Comprehensive checks |
Recommendation: Use both! Pre-commit for fast feedback, CI/CD for comprehensive validation.
Pre-commit hooks are the quality guardian for your repository — preventing bad code from entering version control while maintaining developer velocity through automation.