Originally published on 2026-02-05
Original article (Japanese): シングルバイナリで完結するGit hooks: pre-commitからprekへの移行メモ
Have you ever thought, "Why do I need Python when I'm not working on a Python project?" while using pre-commit?
prek is a Git hooks management tool that reimplements pre-commit in Rust. It allows you to use your existing .pre-commit-config.yaml without needing a Python runtime, and it operates as a single binary. In this article, I will discuss the features of prek, the migration process, and the importance of "portability" over "speed."
Fundamental Issues with pre-commit
While pre-commit is an excellent tool, it has several challenges:
- Python Required - Even for Go/Rust/TypeScript projects, a Python environment is necessary.
- Virtualenv Management - There is a potential conflict with the project's Python version.
-
Complexity in CI/CD - Steps like
setup-python+pip install pre-commitare required. - Onboarding Barriers - New members must start by setting up a Python environment.
This situation often arises in non-Python projects, where you end up needing Python just for Git hooks.
Features of prek
prek (MIT License) addresses these challenges:
1. Single Binary, No Dependencies
# macOS/Linux
curl -LsSf https://github.com/j178/prek/releases/latest/download/prek-installer.sh | sh
# Windows
powershell -c "irm https://github.com/j178/prek/releases/latest/download/prek-installer.ps1 | iex"
No Python runtime is required. It operates with just one binary.
2. Fully Compatible with pre-commit
You can use your existing .pre-commit-config.yaml as is:
repos:
- repo: https://github.com/pre-commit/pre-commit-hooks
rev: v6.0.0
hooks:
- id: trailing-whitespace
- id: end-of-file-fixer
Migration is as simple as pre-commit uninstall && prek install.
3. Speed Improvements
Official benchmarks (Apache Airflow):
| Operation | pre-commit | prek | Ratio |
|---|---|---|---|
| Initial Installation | 187 seconds | 18 seconds | 10.2x |
| Hook Execution | 352 ms | 77 ms | 4.6x |
| Disk Usage | 1.6 GB | 810 MB | Half |
However, this is a "bonus." The essential value will be explained in the next section.
The Value of Portability
The true value of Rust tools lies not in "speed" but in "portability."
Simplified CI/CD
For pre-commit:
# .github/workflows/lint.yml
- uses: actions/setup-python@v5
with:
python-version: '3.11'
- run: pip install pre-commit
- run: pre-commit run --all-files
For prek:
# .github/workflows/lint.yml
- uses: j178/prek-action@v1
The setup steps become unnecessary.
Reduced Dependencies in Development Environments
Dependencies for pre-commit:
Project
├── Python 3.11 (for the app)
└── Python 3.9 (for pre-commit, virtualenv)
└── pre-commit
└── Dependencies for each hook
Dependencies for prek:
Project
└── prek (single binary)
└── Dependencies for each hook
The risk of Python version conflicts is eliminated.
Cross-Platform Compatibility
The same binary works on Windows/macOS/Linux:
# Same command on any OS
prek install
prek run --all-files
This absorbs differences in development environments.
Migration Steps
1. Install prek
# Homebrew
brew install prek
# uv
uv tool install prek
# cargo
cargo install prek
2. Uninstall Existing pre-commit
pre-commit uninstall
3. Install prek
prek install
You can use your .pre-commit-config.yaml as is.
4. Verify Functionality
# Display list of hooks
prek list
# Run on all files
prek run --all-files
# Run specific hooks only
prek run trailing-whitespace end-of-file-fixer
5. Update GitHub Actions
# Before
- uses: pre-commit/action@v3.0.1
# After
- uses: j178/prek-action@v1
Additional Features of prek
Convenient features not available in pre-commit:
List Hooks
$ prek list
.:trailing-whitespace
.:end-of-file-fixer
.:check-yaml
.:check-toml
.:ruff
.:ruff-format
.:mypy
Run with Directory Specification
# Only in the src directory
prek run --directory src
# Multiple directories
prek run --directory src --directory tests
Run Only on Last Commit Targets
prek run --last-commit
Monorepo Support
You can place a .pre-commit-config.yaml for each subproject:
monorepo/
├── .pre-commit-config.yaml # Root
├── frontend/
│ └── .pre-commit-config.yaml
└── backend/
└── .pre-commit-config.yaml
# Run for all projects
prek run
# Run for specific projects only
prek run frontend backend
Points to Note
1. Tool in Development
Currently at v0.3.1. Some languages and subcommands are not yet implemented:
It is recommended to verify the functionality of the hooks you plan to use before production deployment.
2. Unique Features of pre-commit
Some unique features of pre-commit may not be supported. Please check the contents of your .pre-commit-config.yaml before migrating.
Comparison with Other Tools
| Tool | Language | pre-commit Compatible | Dependencies |
|---|---|---|---|
| prek | Rust | ✅ Fully | None |
| lefthook | Go | ❌ Custom Settings | None |
| hk | Rust | ❌ Custom Settings | None |
| Husky | Node.js | ❌ Custom Settings | Node.js |
| pre-commit | Python | - | Python |
Importance of Configuration Compatibility:
While lefthook and hk are also fast, they require rewriting the existing .pre-commit-config.yaml. Since prek can use the configuration file as is, the migration cost is zero.
Adoption Records
Notable OSS projects that have adopted it:
Conclusion
The intrinsic value of prek lies not in "speed" but in "portability":
- Reduction of Dependencies - No Python runtime required.
- Simplification of CI/CD - Fewer setup steps.
- Unification of Development Environments - Cross-platform support.
- Zero Migration Cost - Existing configurations can be used as is.
It is particularly recommended for non-Python projects or for teams looking to simplify their development environments.
If you're interested, please give it a try.
Top comments (0)