Git hooks: автоматизация проверок с pre-commit и Husky
Продвинутое3 минРедакция Innovialabs
Коротко
Git hooks — скрипты, которые Git запускает перед коммитом или пушем; фреймворк pre-commit (Python) и Husky с lint-staged (JS) делают их общими для всей команды и проверяют только изменённые файлы.
Короткий ответ
Git hooks — это скрипты, которые Git сам запускает в определённые моменты: перед коммитом, при записи сообщения коммита, перед пушем. Если скрипт завершился с ошибкой, действие отменяется.
Проблема «голых» хуков: они лежат в .git/hooks, а эта папка не попадает в репозиторий. Поэтому используют инструменты, которые хранят настройки в коде и ставят хуки каждому разработчику:
- pre-commit — фреймворк на Python, работает с любыми языками, популярен в Python-проектах.
- Husky + lint-staged — стандартная связка в JavaScript и TypeScript проектах.
Какие клиентские хуки полезны
| Хук | Когда срабатывает | Что обычно проверяют |
|---|---|---|
pre-commit | до создания коммита | линтер, форматирование, секреты в коде |
commit-msg | после ввода сообщения | формат сообщения коммита |
pre-push | перед отправкой на сервер | быстрые тесты, сборка типов |
Главный принцип: хук должен быть быстрым. Если коммит ждёт минуту, разработчики начнут обходить проверки.
Python: фреймворк pre-commit
Установите пакет и создайте в корне файл .pre-commit-config.yaml:
default_install_hook_types: [pre-commit, commit-msg]
repos:
- repo: https://github.com/pre-commit/pre-commit-hooks
rev: v4.6.0
hooks:
- id: trailing-whitespace
- id: end-of-file-fixer
- id: check-yaml
- id: check-added-large-files
- repo: https://github.com/astral-sh/ruff-pre-commit
rev: v0.6.9
hooks:
- id: ruff
args: [--fix]
- id: ruff-format
- repo: https://github.com/compilerla/conventional-pre-commit
rev: v3.4.0
hooks:
- id: conventional-pre-commit
stages: [commit-msg]
Затем:
pip install pre-commit
pre-commit install # ставит хуки в .git/hooks
pre-commit run --all-files # первый прогон по всему проекту
pre-commit autoupdate # обновить версии в rev
Что важно знать:
- Каждый хук работает в своём изолированном окружении, версии зафиксированы в
rev— у всей команды одинаковые результаты. - По умолчанию проверяются только файлы из коммита.
ruffздесь закрывает и линтинг, и форматирование; можно подключитьblack,isort,mypyи другие.
JavaScript: Husky и lint-staged
Husky управляет хуками, lint-staged запускает команды только для файлов, добавленных в индекс.
npm install --save-dev husky lint-staged
npx husky init
Команда husky init создаёт папку .husky и добавляет скрипт prepare, чтобы хуки ставились автоматически после npm install. Замените содержимое .husky/pre-commit:
npx lint-staged
Настройка lint-staged в package.json:
{
"lint-staged": {
"*.{js,jsx,ts,tsx}": ["eslint --fix", "prettier --write"],
"*.{css,md,json}": "prettier --write"
}
}
Проверка сообщений коммитов через commitlint:
npm install --save-dev @commitlint/cli @commitlint/config-conventional
echo "export default { extends: ['@commitlint/config-conventional'] };" > commitlint.config.js
echo 'npx --no -- commitlint --edit "$1"' > .husky/commit-msg
Теперь сообщение вида fix: исправить расчёт скидки пройдёт, а исправления — нет. Формат конфигурации commitlint зависит от того, использует ли проект ES-модули; сверяйтесь с документацией вашей версии.
Хуки не заменяют CI
Любой хук можно пропустить флагом git commit --no-verify, а у нового разработчика они могут быть просто не установлены. Поэтому:
- те же проверки дублируются в CI — это последний рубеж;
- хуки — это быстрая обратная связь до пуша, а не гарантия;
- тяжёлые проверки (полный набор тестов, сборка) оставляйте в CI или в
pre-push.
Частые ошибки
- Запускать линтер по всему проекту на каждый коммит — медленно. Проверяйте только изменённые файлы.
- Не фиксировать версии инструментов — у разных людей разные результаты.
- Включить строгие правила сразу на старом проекте — сотни ошибок, и хуки отключат. Начните с форматирования, правила добавляйте постепенно.
- Забыть про Windows: скрипты хуков должны работать в Git Bash, избегайте специфичных команд.