DEV Community

Cover image for Git Hooks Completed with a Single Binary: Migration Notes from pre-commit to prek
tumf
tumf

Posted on • Originally published at blog.tumf.dev

Git Hooks Completed with a Single Binary: Migration Notes from pre-commit to prek

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-commit are 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"
Enter fullscreen mode Exit fullscreen mode

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
Enter fullscreen mode Exit fullscreen mode

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
Enter fullscreen mode Exit fullscreen mode

For prek:

# .github/workflows/lint.yml
- uses: j178/prek-action@v1
Enter fullscreen mode Exit fullscreen mode

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
Enter fullscreen mode Exit fullscreen mode

Dependencies for prek:

Project
└── prek (single binary)
    └── Dependencies for each hook
Enter fullscreen mode Exit fullscreen mode

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
Enter fullscreen mode Exit fullscreen mode

This absorbs differences in development environments.

Migration Steps

1. Install prek

# Homebrew
brew install prek

# uv
uv tool install prek

# cargo
cargo install prek
Enter fullscreen mode Exit fullscreen mode

2. Uninstall Existing pre-commit

pre-commit uninstall
Enter fullscreen mode Exit fullscreen mode

3. Install prek

prek install
Enter fullscreen mode Exit fullscreen mode

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
Enter fullscreen mode Exit fullscreen mode

5. Update GitHub Actions

# Before
- uses: pre-commit/action@v3.0.1

# After
- uses: j178/prek-action@v1
Enter fullscreen mode Exit fullscreen mode

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
Enter fullscreen mode Exit fullscreen mode

Run with Directory Specification

# Only in the src directory
prek run --directory src

# Multiple directories
prek run --directory src --directory tests
Enter fullscreen mode Exit fullscreen mode

Run Only on Last Commit Targets

prek run --last-commit
Enter fullscreen mode Exit fullscreen mode

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
Enter fullscreen mode Exit fullscreen mode
# Run for all projects
prek run

# Run for specific projects only
prek run frontend backend
Enter fullscreen mode Exit fullscreen mode

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.

Reference Links

Top comments (0)