Lefthook
The fastest polyglot Git hooks manager out there
A Git hooks manager for Node.js, Ruby and many other types of projects.
- Fast. It is written in Go. Can run commands in parallel.
- Powerful. It allows to control execution and files you pass to your commands.
- Simple. It is single dependency-free binary which can work in any environment.
📖 Read the introduction post
Install
With Go (>= 1.21):
go install github.com/evilmartians/lefthook@latest
With NPM:
npm install lefthook --save-dev
With Ruby:
gem install lefthook
Installation guide with more ways to install lefthook: apt, brew, winget, and others.
Usage
Configure your hooks, install them once and forget about it: rely on the magic underneath.
TL;DR
# Configure your hooks
vim lefthook.yml
# Install them to the git project
lefthook install
# Enjoy your work with git
git add -A && git commit -m '...'
More details
- Configuration for
lefthook.yml
config options. - Usage for lefthook CLI options, supported ENVs, and usage tips.
- Wiki for guides, examples, and benchmarks.
- Discussions for questions, ideas, suggestions.
Why Lefthook
-
Parallel execution
Gives you more speed. Example
pre-push:
parallel: true
-
Flexible list of files
If you want your own list. Custom and prebuilt examples.
pre-commit:
commands:
frontend-linter:
run: yarn eslint {staged_files}
backend-linter:
run: bundle exec rubocop --force-exclusion {all_files}
frontend-style:
files: git diff --name-only HEAD @{push}
run: yarn stylelint {files}
-
Glob and regexp filters
If you want to filter list of files. You could find more glob pattern examples here.
pre-commit:
commands:
backend-linter:
glob: "*.rb" # glob filter
exclude: '(^|/)(application|routes)\.rb$' # regexp filter
run: bundle exec rubocop --force-exclusion {all_files}
-
Execute in sub-directory
If you want to execute the commands in a relative path
pre-commit:
commands:
backend-linter:
root: "api/" # Careful to have only trailing slash
glob: "*.rb" # glob filter
run: bundle exec rubocop {all_files}
-
Run scripts
If oneline commands are not enough, you can execute files. Example.
commit-msg:
scripts:
"template_checker":
runner: bash
-
Tags
If you want to control a group of commands. Example.
pre-push:
commands:
packages-audit:
tags: frontend security
run: yarn audit
gems-audit:
tags: backend security
run: bundle audit
-
Support Docker
If you are in the Docker environment. Example.
pre-commit:
scripts:
"good_job.js":
runner: docker run -it --rm <container_id_or_name> {cmd}
-
Local config
If you a frontend/backend developer and want to skip unnecessary commands or override something into Docker. Description.
# lefthook-local.yml
pre-push:
exclude_tags:
- frontend
commands:
packages-audit:
skip: true
-
Direct control
If you want to run hooks group directly.
$ lefthook run pre-commit
-
Your own tasks
If you want to run specific group of commands directly.
fixer:
commands:
ruby-fixer:
run: bundle exec rubocop --force-exclusion --safe-auto-correct {staged_files}
js-fixer:
run: yarn eslint --fix {staged_files}
$ lefthook run fixer
-
Optional output
If you don't want to see supporting information:
skip_output:
- meta #(version and which hook running)
- success #(output from runners with exit code 0)
Table of contents:
Guides
- Install with Node.js
- Install with Ruby
- Install with Homebrew
- Install with Winget
- Install for Debian-based Linux
- Install for RPM-based Linux
- Install for Arch Linux
- Usage
- Configuration
- Troubleshooting