W3docs

Git-хуки

Git-хуки — скрипты, запускаемые автоматически в жизненном цикле Git для линтинга, тестирования и валидации. Пример pre-commit хука.

Что такое Git-хуки

Git-хуки — это скрипты, которые Git запускает автоматически при наступлении определённых событий: создании коммита, слиянии, пуше и других. Они позволяют встраивать пользовательские действия в жизненный цикл Git: запускать линтер перед каждым коммитом, проверять формат сообщения коммита или блокировать пуш при провале тестов. Именно с помощью хуков команды внедряют локальные проверки качества кода — ещё до того, как плохой код покинет машину разработчика.

На этой странице рассказывается, где хранятся хуки, в чём разница между клиентскими и серверными хуками, какие хуки наиболее полезны с рабочими примерами, как хук прерывает операцию, как его обойти и как делиться хуками в команде.

Git-хуки, срабатывающие на этапах жизненного цикла коммита и пуша

Где хранятся хуки

В каждом репозитории есть директория .git/hooks, содержащая примеры скриптов с суффиксом .sample. Чтобы активировать хук, добавьте исполняемый скрипт с точным именем хука и без расширения:

ls .git/hooks
# pre-commit.sample  commit-msg.sample  pre-push.sample ...

Удалите суффикс .sample (или создайте файл заново) и сделайте его исполняемым:

chmod +x .git/hooks/pre-commit

Хук может быть написан на любом языке при условии, что файл является исполняемым и начинается с подходящей строки shebang (#!/bin/sh, #!/usr/bin/env python3, #!/usr/bin/env node и т. д.). Git важно лишь одно: файл должен называться точно так же, как известный хук, быть исполняемым и возвращать код завершения.

Клиентские и серверные хуки

  • Клиентские хуки выполняются на вашей машине при локальных операциях — создании коммита и пуше. Они отлично подходят для линтинга и тестирования.
  • Серверные хуки (например, pre-receive и post-receive) запускаются на удалённом репозитории при получении пуша — полезны для централизованного применения политик.

Наиболее часто используются клиентские хуки:

ХукСрабатываетТипичное применение
pre-commitДо создания коммитаЛинтинг и тестирование проиндексированных файлов; прерывание при ошибке.
prepare-commit-msgДо открытия редактора сообщенияВставка шаблона или номера задачи.
commit-msgПосле написания сообщенияПрименение соглашения о формате сообщений.
post-commitПосле завершения коммитаОтправка уведомления; не влияет на коммит.
pre-pushДо отправки пушаЗапуск полного набора тестов в качестве финальной проверки.

Как хук прерывает операцию

Весь механизм управления строится на коде завершения. Для хуков типа «pre-» (pre-commit, pre-push, commit-msg и др.):

  • Завершение с кодом 0 → хук одобрил операцию, и Git продолжает выполнение.
  • Завершение с ненулевым кодом → Git отменяет операцию. Коммит не создаётся, пуш не отправляется.

Хуки типа «post-» (post-commit, post-merge и др.) выполняются после того, как действие уже завершено, поэтому их код завершения игнорируется — они не могут ничего отменить. Используйте их для уведомлений, но не для валидации.

Пример pre-commit хука

Этот хук pre-commit запускает линтер проекта и блокирует коммит при обнаружении проблем. Поскольку sh прерывает выполнение при сбое команды благодаря set -e, дополнительная проверка $? не нужна:

#!/bin/sh
set -e
echo "Running lint..."
npm run lint

Если npm run lint завершается с ненулевым кодом, set -e передаёт этот код дальше и коммит прерывается. Если предпочтительнее пользовательское сообщение, проверьте результат явно:

#!/bin/sh
if ! npm run lint; then
  echo "Lint failed — commit aborted. Fix the issues and try again."
  exit 1
fi

Сохраните файл как .git/hooks/pre-commit и выполните chmod +x .git/hooks/pre-commit.

Пример commit-msg хука

Хук commit-msg получает один аргумент: путь к временному файлу с предлагаемым сообщением. Прочитайте этот файл, проверьте его и завершите с ненулевым кодом для отклонения. Данный пример применяет соглашение в стиле Conventional Commits:

#!/bin/sh
# $1 is the path to the file containing the commit message
message=$(head -n1 "$1")
pattern='^(feat|fix|docs|style|refactor|test|chore): .+'

if ! echo "$message" | grep -Eq "$pattern"; then
  echo "Commit message must start with feat:, fix:, docs:, etc."
  exit 1
fi

Обход хука

Хук — это страховочная сетка, а не стена. Если вам действительно нужно пропустить хуки pre-commit и commit-msg для одной операции, используйте флаг --no-verify:

git commit --no-verify -m "WIP: skip checks"
git push --no-verify

Используйте это редко — обход линтера открывает путь некачественному коду в историю.

Общий доступ к хукам в команде

Поскольку директория .git/hooks не попадает в коммиты, хуки не передаются вместе с клоном. Команды решают это, храня хуки в отслеживаемой директории и направляя на неё Git:

git config core.hooksPath .githooks

Теперь Git ищет хуки в отслеживаемой директории .githooks/ вместо .git/hooks. Зафиксируйте скрипты там, сделайте их исполняемыми, и каждый участник команды получит их после выполнения той же команды git config (или после того, как это сделает скрипт настройки). Подробнее о хранении настроек репозитория — в разделе Git config.

Такие инструменты, как Husky, автоматизируют именно это для JavaScript-проектов, подключая общие хуки во время установки. Для политик, которые нельзя позволить обойти с помощью --no-verify, применяйте серверные хуки или защиту веток на платформе хостинга — ведь клиентские хуки всегда остаются на машине разработчика.

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

  • git commit — команда, которую оборачивают хуки pre-commit и commit-msg.
  • Подпись коммитов — подтверждение авторства, часто используется вместе с хуками.
  • Git config — место хранения core.hooksPath и других настроек.
  • Git alias — сокращения для команд, запускаемых хуками.

Практика

Практика
Какие утверждения о Git-хуках верны?
Какие утверждения о Git-хуках верны?
Was this page helpful?