Хуки Git: как автоматизировать проверки до коммита
Хук Git может остановить коммит с ошибкой форматирования, запускать тесты перед отправкой и не пускать очевидный мусор в репозиторий. Разбираем native hooks, pre-commit и CI: что выбрать и где автоматизация ломается.

Одна строка с пробелами в конце файла, забытый отладочный вывод или падающий тест могут попасть в общий репозиторий за секунду. Хуки Git переносят такие проверки ближе к моменту ошибки: локальный pre-commit блокирует коммит, pre-push проверяет ветку перед отправкой, а CI остаётся последним независимым барьером. Ниже — рабочая схема для Git 2.x, которую можно внедрить за 15–30 минут без стороннего сервера.
Что именно автоматизируют хуки Git
Хук — это исполняемый файл с фиксированным именем, который Git запускает на определённом этапе операции. Чаще всего проверки ставят перед коммитом или отправкой изменений. Такой скрипт получает контекст операции, возвращает код завершения и может разрешить или остановить действие.
Для ежедневной разработки полезно разделить проверки по цене ошибки:
- быстрые проверки — пробелы в конце строк, формат файлов, синтаксис;
- проверки проекта — линтеры, статический анализ, модульные тесты;
- защитные проверки — случайные секреты, крупные файлы, запрещённые расширения;
- серверные проверки — то, что нельзя доверять только рабочей станции разработчика.
Технический термин: код завершения — число, которое процесс возвращает операционной системе. Нулевой код обычно означает успех, ненулевой — ошибку; Git использует это значение, чтобы понять, продолжать ли операцию.
Хук должен быть коротким и предсказуемым: быстрая проверка, понятная ошибка, одна команда для повторного запуска.
Куда ставить проверку
| Этап | Когда запускается | Что проверять | Главный риск |
|---|---|---|---|
pre-commit | Перед созданием коммита | Форматирование, линтер, staged-файлы | Медленный скрипт раздражает разработчиков |
commit-msg | После ввода сообщения коммита | Шаблон и обязательный идентификатор задачи | Правило может быть слишком жёстким для быстрых исправлений |
pre-push | Перед отправкой ветки | Тесты и проверки, дорогие для каждого коммита | Пуш превращается в долгую операцию |
| CI | После отправки в удалённый репозиторий | Полный набор проверок в чистой среде | Ошибка обнаруживается позже |
На практике быстрые проверки стоит запускать в pre-commit, более дорогие — в pre-push и CI. Хук не заменяет CI: его можно обойти параметром --no-verify, отключить локально или не установить на новой машине.
Базовая схема на встроенных хуках Git
1. Храним хуки рядом с проектом
По умолчанию Git ищет хуки в каталоге .git/hooks. Он не предназначен для версионирования: файлы из него обычно не попадают в коммит. Поэтому создайте отдельный каталог в репозитории и укажите Git использовать его как каталог хуков:
mkdir -p .githooks
git config core.hooksPath .githooks
После этого настройка действует для текущего репозитория. Проверить её можно командой:
git config --get core.hooksPath
В ответе должно появиться .githooks. Если команда ничего не вывела, Git продолжает использовать стандартный путь.
2. Добавляем быстрый pre-commit
Создайте файл .githooks/pre-commit. Скрипт ниже проверяет только то, что попадёт в ближайший коммит: это важно, если в рабочем каталоге есть незавершённые изменения.
#!/bin/sh
set -eu
if ! git diff --cached --check; then
echo "Коммит остановлен: исправьте пробелы или конфликтные маркеры в staged-файлах." >&2
exit 1
fi
echo "pre-commit: базовая проверка пройдена"
Команда git diff --cached --check ищет распространённые проблемы в индексированных изменениях, включая пробелы в конце строк. Сделайте файл исполняемым:
chmod +x .githooks/pre-commit
Теперь добавьте тестовую строку с пробелами в конец, выполните git add и попробуйте создать коммит. Git должен остановить операцию и вывести сообщение о проблеме.
3. Запускаем проектные проверки
Команду тестов добавляйте только после того, как она существует в самом проекте. Не стоит зашивать в общий хук универсальное имя вроде run-tests: в одном репозитории это будет npm-скрипт, в другом — команда Python или Gradle.
#!/bin/sh
set -eu
if ! git diff --cached --check; then
echo "Коммит остановлен: найдены ошибки в diff." >&2
exit 1
fi
if ! npm test; then
echo "Коммит остановлен: тесты завершились с ошибкой." >&2
exit 1
fi
echo "pre-commit: проверки пройдены"
Этот вариант подходит только проекту, где в репозитории есть рабочий скрипт npm test и установлены зависимости. Для проекта на другом стеке замените команду на ту, что указана в его документации. Проверка успешна, если обе команды завершаются с кодом 0 и Git создаёт коммит.
Три подхода и их цена
Встроенные хуки дают полный контроль, но настройку нужно повторить на каждой рабочей копии. Менеджер хуков упрощает подключение линтеров, а CI обеспечивает обязательную проверку на сервере. Это не взаимоисключающие варианты.
| Подход | Плюс | Цена | Когда выбирать |
|---|---|---|---|
| Native hooks | Нет зависимости от фреймворка | Нужно отдельно установить путь и права | Небольшой проект или несколько простых проверок |
| Менеджер хуков | Единая установка и конфигурация | Появляется инструмент и его собственный жизненный цикл | Много языков, линтеров и команд |
| Только CI | Одинаковая чистая среда для всех | Ошибка обнаруживается после push, тратится время на цикл | Обязательный серверный барьер и финальная проверка |
Критерий выбора простой: если проверка занимает секунды и относится к изменённым файлам, ставьте её в pre-commit. Если она занимает минуты или требует внешних сервисов, переносите в pre-push либо CI. Если нарушение недопустимо, проверяйте его и локально, и на сервере.
Что ломается на практике
Хук не запускается
Чаще всего забывают сделать файл исполняемым или указывают неправильный core.hooksPath. Проверьте оба значения командами ls -l .githooks/pre-commit и git config --show-origin --get core.hooksPath. У файла должен быть установлен флаг выполнения.
Хук видит не те файлы
git diff --check без параметров проверяет рабочее дерево, а не обязательно содержимое будущего коммита. Для проверки staged-изменений используйте git diff --cached --check. Иначе скрипт может остановить коммит из-за незавершённой работы, которую вы не собирались фиксировать.
Проверка проходит локально, но падает в CI
Локальная машина может использовать другую версию Node.js, Python, форматтера или операционной системы. Зафиксируйте версии в проекте, запускайте в CI те же команды и не скрывайте ошибку оператором --no-verify. Хуки ускоряют обратную связь, но только CI проверяет результат в контролируемой среде.
Коммит невозможно сделать в аварийной ситуации
Иногда тесты падают из-за внешней базы, недоступного сервиса или уже известной ошибки. Сначала исправьте причину. Если нужно сохранить промежуточную работу, явно используйте git commit --no-verify, а затем добейтесь прохождения CI и не оставляйте такой обход частью обычного процесса.
Что настроить дальше
После базового pre-commit добавьте одинаковую проверку в CI. Затем измерьте время каждого шага: быстрые проверки должны давать ответ за секунды, а не превращать каждый коммит в ожидание. Для больших репозиториев запускайте линтер только на изменённых файлах, а полный набор тестов оставляйте для pre-push и CI.
Следующий полезный шаг — определить один обязательный серверный набор: форматирование, статический анализ, тесты и проверка секретов. Локальный хук помогает разработчику не ошибиться, а CI не позволяет команде принять результат на веру.
Проверка рекламы на риски: Что в макете вызовет вопросы ФАС: превосходные степени, сравнения, обещания результата, маркировка.
Спросить за 40 ₽Источники: Git documentation: githooks, Git documentation: git-config, core.hooksPath
Частые вопросы
Можно ли хранить хуки Git в репозитории?
Почему pre-commit не запускается после клонирования проекта?
Можно ли пропустить проверку хуков?
Что делать, если тесты в pre-commit выполняются слишком долго?
Хуки Git защищают репозиторий от секретов?
Материал носит информационный характер и подготовлен редакцией «Агентуры». Он не является офертой, рекламой или индивидуальной консультацией. Упомянутые продукты, компании и торговые знаки принадлежат их правообладателям. Перед принятием решений, влекущих юридические или финансовые последствия, обратитесь к профильному специалисту.