git hooks: автоматизация
Скрипты, которые Git запускает автоматически при определённых событиях: commit, push, merge, checkout и других.
Зачем нужно
Git hooks позволяют автоматизировать проверки и действия прямо в процессе работы с репозиторием — без CI/CD. Например: запускать линтер перед каждым коммитом, проверять формат сообщения коммита, запускать тесты перед push или обновлять зависимости после checkout. Это первый барьер качества, который срабатывает на машине разработчика.
Где используется
pre-commit: запуск линтера, форматтера, проверки секретовcommit-msg: валидация формата сообщения (Conventional Commits)pre-push: запуск тестов перед отправкой ветки на remotepost-merge/post-checkout: обновлениеnode_modulesпосле переключения веток
Основной контент
Расположение hooks
# Hooks хранятся в .git/hooks/ (не под контролем Git)
ls .git/hooks/
# applypatch-msg.sample pre-commit.sample
# commit-msg.sample pre-merge-commit.sample
# pre-push.sample post-commit.sample
# ...
# Убрать .sample — активировать hook
cp .git/hooks/pre-commit.sample .git/hooks/pre-commit
chmod +x .git/hooks/pre-commit
Основные типы hooks
| Hook | Когда запускается | Код возврата |
|---|---|---|
pre-commit |
Перед созданием commit | Ненулевой = отменить commit |
commit-msg |
После ввода сообщения | Ненулевой = отменить commit |
pre-push |
Перед git push |
Ненулевой = отменить push |
post-commit |
После commit | Игнорируется |
post-merge |
После git merge |
Игнорируется |
post-checkout |
После git checkout |
Игнорируется |
pre-rebase |
Перед rebase | Ненулевой = отменить rebase |
Примеры hook-скриптов
# .git/hooks/pre-commit — запустить ESLint
#!/bin/bash
npm run lint
if [ $? -ne 0 ]; then
echo "Lint failed. Commit aborted."
exit 1
fi
# .git/hooks/commit-msg — проверить формат Conventional Commits
#!/bin/bash
MSG=$(cat "$1")
PATTERN="^(feat|fix|docs|style|refactor|test|chore|perf|ci|build|revert)(\(.+\))?: .{1,100}"
if ! echo "$MSG" | grep -qP "$PATTERN"; then
echo "Invalid commit message format. Use: type(scope): description"
exit 1
fi
# .git/hooks/post-merge — обновить зависимости
#!/bin/bash
CHANGED=$(git diff-tree -r --name-only --no-commit-id ORIG_HEAD HEAD)
if echo "$CHANGED" | grep -q "package.json"; then
echo "package.json changed — running npm install"
npm install
fi
Husky — hooks в системе контроля версий
Стандартная проблема hooks: .git/hooks не попадает в репозиторий, каждый разработчик должен настраивать вручную. Husky решает это, сохраняя hooks в .husky/ и автоматически подключая их через package.json.
# Установка
npm install -D husky
npx husky init
# Добавить pre-commit hook
echo "npm run lint" > .husky/pre-commit
# Добавить commit-msg hook (для commitlint)
echo "npx --no -- commitlint --edit \$1" > .husky/commit-msg
// package.json
{
"scripts": {
"prepare": "husky"
}
}
Частые ошибки
- Забыть
chmod +x— hook без прав на выполнение молча игнорируется - Не учесть ОС —
.git/hooksс bash-скриптами не работают на Windows без WSL или Git Bash - Обойти hooks через
--no-verify—git commit --no-verifyпропускает все hooks; используй только в экстренных случаях - Медленный pre-commit — запуск полного тест-сьюта блокирует работу; pre-commit должен быть быстрым (линтер, не тесты)