Git hooks: автоматизация проверок перед коммитом и пушем
Пишем реальные bash-хуки, разбираем клиентские и серверные события Git, сравниваем Husky, pre-commit и lefthook — с готовыми примерами конфигов.
Вы когда-нибудь отправляли коммит с опечаткой в сообщении — или пушили сырой код, который ломал CI? Git hooks позволяют этого избежать: это скрипты, которые автоматически запускаются при определённых событиях в Git. Настроил один раз — и линтер, проверка формата, тесты выполняются сами, без участия разработчика.
В этой статье разберём клиентские и серверные хуки, напишем реальные bash-скрипты и сравним инструменты для управления хуками в команде: Husky, pre-commit framework и lefthook.
Ключевые выводы
— Git hooks — скрипты в .git/hooks/, выполняемые при событиях Git (коммит, пуш, мерж)
— Клиентские хуки: pre-commit, commit-msg, pre-push и другие — запускаются на машине разработчика
— Серверные хуки: pre-receive, update, post-receive — контролируют пуши на сервере
— Husky, pre-commit framework и lefthook упрощают управление хуками в команде
— Хуки — это локальная автоматизация; CI/CD — серверная: они дополняют друг друга
Эта статья — часть нашего полного путеводителя по Git. Там — весь маршрут: от первого коммита до продвинутых workflow.
Что такое Git hooks
Git hooks — это скрипты, которые Git запускает автоматически при определённых событиях: перед созданием коммита, после пуша, при мерже. Они живут в директории .git/hooks/ вашего репозитория.
По умолчанию там лежат примеры с расширением .sample — они неактивны. Чтобы активировать хук, достаточно убрать расширение и сделать файл исполняемым:
Скрипт может быть написан на любом языке: bash, Python, Ruby, Node.js — лишь бы интерпретатор был доступен в системе. Хук завершается с кодом 0 — операция продолжается; с ненулевым — Git прерывает её.
Клиентские хуки
Клиентские хуки выполняются на машине разработчика. Они не копируются при клонировании репозитория — каждый разработчик настраивает их сам (или через инструменты вроде Husky).
- pre-commit — запускается до того, как Git создаст коммит. Здесь запускают линтеры, форматтеры, статический анализ. Если хук вернул ненулевой код — коммит не создаётся.
- prepare-commit-msg — запускается после создания сообщения коммита по умолчанию, но до его открытия в редакторе. Используется для автоматического добавления номера задачи из названия ветки.
- commit-msg — получает путь к файлу с сообщением коммита. Здесь проверяют, соответствует ли сообщение формату (например, Conventional Commits).
- post-commit — запускается после создания коммита. Используется для уведомлений; не влияет на сам коммит.
- pre-push — запускается перед
git push. Здесь запускают тесты или запрещают пуш в защищённые ветки. - post-checkout — вызывается после
git checkout,git switchиgit clone. Удобен для автоматической установки зависимостей после смены ветки.
Серверные хуки
Серверные хуки выполняются на стороне Git-сервера (GitLab, Gitea, собственный сервер). Они позволяют централизованно контролировать все пуши — независимо от настроек на машинах разработчиков.
- pre-receive — вызывается при получении пуша, до обновления веток. Может отклонить весь пуш целиком: проверяет права, политику коммитов, размер файлов.
- update — аналог
pre-receive, но вызывается отдельно для каждой обновляемой ветки. Позволяет разрешить пуш в одни ветки и запретить в другие. - post-receive — запускается после успешного пуша. Используется для уведомлений, триггеров деплоя, синхронизации с внешними системами.
Практические примеры
pre-commit: запуск линтера перед коммитом
Хук проверяет только те файлы, которые добавлены в индекс. Это ускоряет проверку в больших проектах:
commit-msg: проверка формата сообщения
Хук проверяет, соответствует ли сообщение коммита формату Conventional Commits (feat: ..., fix: ..., docs: ... и т. д.):
pre-push: запрет пуша в main/master
Хук предотвращает случайный прямой пуш в защищённые ветки:
Инструменты: Husky, pre-commit framework, lefthook
Проблема «голых» хуков в том, что .git/hooks/ не попадает в репозиторий. Каждый разработчик должен настраивать их вручную. Инструменты решают эту проблему — хуки версионируются вместе с кодом и устанавливаются автоматически.
Husky — самый популярный выбор для JavaScript-проектов. Хуки описываются в файлах директории .husky/ и устанавливаются через npm install. Интегрируется с lint-staged для запуска проверок только на изменённых файлах.
pre-commit framework — мощный инструмент для Python-проектов (и не только). Хуки описываются в .pre-commit-config.yaml. Поддерживает большую экосистему готовых хуков — для Python, Go, Terraform, Docker и других технологий.
Lefthook — быстрый инструмент на Go, работает в любом проекте независимо от языка. Конфигурация в lefthook.yml. Поддерживает параллельный запуск хуков, что заметно ускоряет проверку в монорепозиториях.
Краткое сравнение инструментов:
- Husky — лучший выбор для Node.js/фронтенд-проектов. Глубокая интеграция с npm-экосистемой.
- pre-commit framework — богатая экосистема готовых хуков, идеален для Python и мультиязычных проектов.
- lefthook — самый быстрый, не зависит от языка, хорошо работает в монорепозиториях с параллельными задачами.
Хуки и CI/CD: дополняют, а не заменяют
Git hooks и CI/CD решают одну задачу — автоматическую проверку кода — но на разных уровнях. Хуки работают локально, до отправки кода на сервер. Это быстрая первая линия обороны: разработчик получает обратную связь за секунды, не дожидаясь очереди в CI.
CI/CD — это серверная автоматизация: она запускается независимо от хуков и не может быть отключена разработчиком. CI выполняет более тяжёлые проверки: интеграционные тесты, сборку Docker-образов, деплой. О том, как выстроить полный пайплайн, читайте в roadmap DevOps-инженера.
Правило: хуки проверяют то, что можно проверить быстро (секунды) — линт, форматирование, формат сообщения. CI проверяет то, что требует инфраструктуры — тесты с базой данных, e2e, performance benchmarks. Дублировать медленные проверки в хуках не стоит — разработчики будут обходить их через git commit --no-verify.
Часто задаваемые вопросы
Можно ли обойти Git hook?
Да: флаг --no-verify (или -n) отключает хуки для конкретного коммита или пуша. Именно поэтому клиентские хуки не являются надёжной защитой — они страхуют от случайных ошибок, но не от намеренного обхода. Для строгого контроля используйте серверные хуки или CI/CD.
Почему хуки не копируются при git clone?
Директория .git/ полностью локальная и никогда не отправляется на сервер — это намеренное решение Git. Для совместного использования хуков в команде нужны инструменты: Husky, pre-commit framework или lefthook. Они хранят конфигурацию хуков в обычных файлах репозитория и устанавливают их автоматически.
На каком языке можно писать хуки?
На любом — bash, Python, Ruby, Node.js, Go и других. Главное, чтобы в первой строке файла был корректный shebang: #!/bin/bash или #!/usr/bin/env python3. Самый универсальный вариант — bash: он есть на любой Unix-подобной системе и не требует установки зависимостей.
Git hooks — мощный инструмент, который превращает локальную разработку в управляемый процесс. Пять минут на настройку pre-commit и commit-msg экономят часы ревью в будущем. Начните с одного хука, убедитесь, что он не замедляет работу, и постепенно добавляйте остальные. Подробнее о том, как hooks вписываются в общий рабочий процесс с ветками и пулл-реквестами, читайте в статье про Git Flow, GitHub Flow и Trunk-Based разработку.