Pre-commit is a framework for managing and maintaining multi-language pre-commit hooks that run automatically before each git commit, ensuring code quality and consistency.
Pre-commit helps maintain code quality by:
- Running code quality checks before each commit
- Supporting hooks for multiple languages and tools
- Preventing commits that don't meet quality standards
- Automating code formatting and linting
- Ensuring consistent code style across the project
- Integrating with CI/CD pipelines
- Supporting custom hooks for project-specific checks
Pre-commit is included as a development dependency:
# Install with other development dependencies
uv sync --devTo install it directly:
uv pip install pre-commitAfter installation, you need to install the git hooks:
uv run pre-commit installIn this project, Pre-commit is used to:
- Run code quality checks before each commit
- Enforce consistent code style and formatting
- Catch common issues early in the development process
- Ensure documentation is properly formatted
- Run security checks on the codebase
Pre-commit is configured in the .pre-commit-config.yaml file:
repos:
- repo: https://github.com/astral-sh/ruff-pre-commit
rev: v0.1.6
hooks:
- id: ruff
args: [--fix]
- id: ruff-format
- repo: https://github.com/pre-commit/mirrors-mypy
rev: v1.7.1
hooks:
- id: mypy
additional_dependencies: [pydantic, types-requests]
# Additional hooks...# Run pre-commit on all files
uv run pre-commit run --all-files
# Run pre-commit on staged files
uv run pre-commit run
# Run a specific hook
uv run pre-commit run ruff --all-files# Skip specific hooks
uv run pre-commit run --all-files --hook-stage commit --skip ruff
# Run hooks on specific files
uv run pre-commit run --files src/module.py tests/test_module.py
# Show hook output even if successful
uv run pre-commit run --verbose$ uv run pre-commit run --all-files
Ruff............................................................Passed
Ruff Format....................................................Passed
mypy...........................................................Passed
Bandit.........................................................Passed
Vulture........................................................Passed
Pyright........................................................Passed$ uv run pre-commit run --all-files
Ruff............................................................Failed
- hook id: ruff
- exit code: 1
src/module.py:10:1: F401 [*] `os` imported but unused
src/module.py:25:5: E501 Line too long (88 > 79 characters)Pre-commit supports different types of hooks:
- pre-commit: Runs before committing
- pre-push: Runs before pushing
- pre-merge-commit: Runs before merge commits
- pre-rebase: Runs before rebasing
- commit-msg: Runs to validate commit messages
- prepare-commit-msg: Runs to prepare commit messages
- Run hooks on all files periodically: Use
pre-commit run --all-filesto check the entire codebase. - Keep hooks fast: Ensure hooks run quickly to avoid disrupting the development workflow.
- Use auto-fixing hooks: Prefer hooks that can automatically fix issues when possible.
- Update hooks regularly: Keep hook versions updated to benefit from improvements and bug fixes.
- Include pre-commit in CI: Run pre-commit in CI to ensure all contributors follow the same standards.
- Document custom hooks: If you add custom hooks, document their purpose and requirements.
- Use local hooks for project-specific checks: Add local hooks for checks specific to your project.
| Hook | Purpose |
|---|---|
ruff |
Python linter and formatter |
mypy |
Static type checking |
black |
Python code formatter |
isort |
Import sorter |
flake8 |
Python style guide enforcement |
bandit |
Security linter |
prettier |
Multi-language formatter |
markdownlint |
Markdown linter |
shellcheck |
Shell script linter |
To skip hooks for a specific commit:
git commit --no-verify -m "Your commit message"To update hooks to their latest versions:
uv run pre-commit autoupdateIf you encounter issues with cached results or pyi files:
uv run pre-commit clean
poe mkinit