git hooks: автоматизация

Скрипты, которые Git запускает автоматически при определённых событиях: commit, push, merge, checkout и других.

Зачем нужно

Git hooks позволяют автоматизировать проверки и действия прямо в процессе работы с репозиторием — без CI/CD. Например: запускать линтер перед каждым коммитом, проверять формат сообщения коммита, запускать тесты перед push или обновлять зависимости после checkout. Это первый барьер качества, который срабатывает на машине разработчика.

Где используется

  • pre-commit: запуск линтера, форматтера, проверки секретов
  • commit-msg: валидация формата сообщения (Conventional Commits)
  • pre-push: запуск тестов перед отправкой ветки на remote
  • post-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-verifygit commit --no-verify пропускает все hooks; используй только в экстренных случаях
  • Медленный pre-commit — запуск полного тест-сьюта блокирует работу; pre-commit должен быть быстрым (линтер, не тесты)

Связанные темы

Ресурсы