Хук — исполняемый файл, который Git запускает перед коммитом, после ввода сообщения или перед отправкой в удалённый репозиторий. Проверки работают локально и ловят ошибку за секунды, а не после падения CI. Но хуки не копируются при клонировании и отключаются флагом --no-verify, поэтому нужна общая точка входа для команды.

Как устроены хуки

Git ищет исполняемые файлы в каталоге .git/hooks. При инициализации репозитория там появляются примеры с суффиксом .sample: они не активны, пока вы не уберёте суффикс и не выставите бит исполнения. Многие хуки получают аргументы, а pre-push и серверные — данные на стандартный ввод. Результат возвращается кодом выхода: ноль — продолжить, ненулевой — прервать. Ошибки печатайте в stderr, иначе Git может их проглотить.

Клиентские хуки делятся на группы. pre-commit запускается до создания коммита и идеален для быстрых проверок. commit-msg получает путь к файлу с сообщением и проверяет формат. pre-push вызывается перед отправкой и подходит для тестов, которые не должны занимать секунды. Серверные хуки, например pre-receive, живут на Git-сервере и не зависят от настроек разработчика.

ls -l .git/hooks
cat .git/hooks/pre-commit.sample
git config --get core.hooksPath
git help githooks

Первый pre-commit: секреты и мусор

Начните с проверок, которые дают мгновенную пользу и почти не дают ложных срабатываний: запрет больших файлов, поиск отладочных маркеров, грубая проверка на приватные ключи. Смотрите на индекс, а не на рабочую копию: в коммит попадёт только добавленное через git add.

#!/bin/sh
set -e
git diff --cached --name-only --diff-filter=ACM | while IFS= read -r file; do
  [ -f "$file" ] || continue
  size=$(wc -c < "$file")
  [ "$size" -le 1048576 ] || { echo "Слишком большой файл: $file" >&2; exit 1; }
done
if git grep --cached -n -I -E 'BEGIN (RSA|OPENSSH|EC) PRIVATE KEY' -- .; then
  echo "В индексе найден приватный ключ" >&2
  exit 1
fi
exit 0

Скрипт простой и не пытается угадать все форматы секретов. Для настоящего проекта подключите специализированный сканер, но даже такая проверка отсекает случайно добавленный id_rsa. Не забывайте про chmod +x .git/hooks/pre-commit, иначе Git молча проигнорирует файл.

commit-msg и единый формат сообщений

Второй полезный хук проверяет сообщение коммита. Если команда приняла Conventional Commits, правило описывается регулярным выражением. Хук получает путь к временному файлу в $1; читайте первую строку и сравнивайте с шаблоном. Длинную тему отклоняйте: её неудобно читать в истории.

#!/bin/sh
subject=$(head -n 1 "$1")
pattern='^(feat|fix|docs|style|refactor|perf|test|build|ci|chore|revert)(\([a-z0-9._-]+\))?: .{1,72}$'
printf '%s' "$subject" | grep -Eq "$pattern" || {
  echo "Формат: feat(scope): краткое описание до 72 символов" >&2
  exit 1
}
exit 0

Проверка должна быть предсказуемой. Если правило разрешает русский текст после двоеточия, не ограничивайте его латиницей. Если проект использует трекер задач, требуйте номер задачи, но не усложняйте шаблон до предела.

pre-push: тесты перед отправкой

pre-push получает имя удалённого репозитория и URL, а на stdin — список ссылок. Полноценные тесты занимают минуты, поэтому запускайте быстрый набор: линтер, проверку типов, модульные тесты затронутых модулей. Тяжёлые интеграционные тесты оставьте CI, иначе разработчики начнут отключать хуки.

#!/bin/sh
set -e
echo "Быстрые проверки перед push..."
python -m ruff check .
python -m pytest -q tests/unit
exit 0

Не запускайте в хуке команды, которые меняют рабочее дерево: форматирование и автоматические коммиты внутри pre-commit легко приводят к путанице. Пусть форматтер исправляет код отдельной командой, а хук только сообщает о нарушении.

Общие хуки в репозитории

Каталог .git/hooks не версионируется, поэтому договориться о проверках через него нельзя. Решение — хранить скрипты в репозитории и указать Git на них через core.hooksPath. Создайте каталог .githooks, положите туда исполняемые файлы и добавьте настройку. Каждый разработчик выполняет одну команду после клонирования; её же включите в скрипт первичной настройки.

mkdir -p .githooks
cp .git/hooks/pre-commit .githooks/pre-commit
git config core.hooksPath .githooks
chmod +x .githooks/pre-commit

Путь в core.hooksPath может быть абсолютным или относительным. Относительный удобнее, но проверьте поведение в связанных worktree: Git разрешает его от корня рабочего дерева. Если хуки должны быть обязательными, продублируйте ключевые проверки в CI: настройка core.hooksPath локальна и не гарантирует дисциплину.

pre-commit framework и сопровождение

Писать bash-скрипты для каждой проверки утомительно. Framework pre-commit управляет хуками из файла .pre-commit-config.yaml, скачивает и кэширует версии инструментов и запускает проверки только по изменённым файлам. После установки пакета выполните pre-commit install — он пропишет точку входа в .git/hooks/pre-commit. Полный прогон запускается командой pre-commit run --all-files.

repos:
  - repo: https://github.com/pre-commit/pre-commit-hooks
    rev: v4.6.0
    hooks:
      - id: trailing-whitespace
      - id: end-of-file-fixer
      - id: check-added-large-files
        args: [--maxkb=512]
      - id: check-merge-conflict

Фиксируйте rev на теге, а не на ветке: иначе проверки изменятся без вашего участия. В примере указан конкретный тег; актуальный смотрите на странице проекта. Обновляйте версии отдельным коммитом через pre-commit autoupdate. Кэш framework хранится в домашнем каталоге, поэтому первый запуск может быть долгим, особенно в CI.

Флаг —no-verify и дисциплина

Флаг --no-verify пропускает клиентские хуки. Это аварийный выход для срочной правки, а не ежедневный режим. Если хук мешает, упростите его, а не отключайте. Проверки должны занимать единицы секунд; всё, что дольше, переносится в pre-push или CI. Выводите понятное сообщение: что не так и как это исправить.

  • Хуки не заменяют CI: они лишь ускоряют обратную связь.
  • Не храните секреты в репозитории, даже если хук их ищет.
  • Проверяйте индекс, а не только рабочее дерево.
  • Делайте скрипты идемпотентными и без интерактивных запросов.
  • Документируйте установку хуков в README или make setup.
  • Для Windows-разработчиков проверьте переводы строк и права файлов.
git commit --no-verify -m "wip"
pre-commit run --all-files
git config --unset core.hooksPath
git log -1 --format=%B

Итог

Git hooks — дешёвый способ перенести часть проверок влево, на машину разработчика. Начните с pre-commit для больших файлов и секретов, добавьте commit-msg для единого формата и pre-push для быстрых тестов. Храните скрипты в репозитории через core.hooksPath, а ключевые правила дублируйте в CI. Тогда хук останется помощником, а не единственной линией обороны.

Насколько публикация полезна?

Нажмите на звезду, чтобы оценить!

Средняя оценка 0 / 5. Количество оценок: 0

Оценок пока нет. Поставьте оценку первым.

Поделиться: Telegram ВКонтакте