0052 — pre-commit

Содержимое страницы

Утилита pre-commit изменила моё представление о работе с Git и статическими анализаторами. Какую же задачу она решает?

pre-commit решает задачу проверки кода перед его фиксацией в Git.

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

«Из коробки» pre-commit уже имеет несколько готовых правил, но ещё больше можно получить путём установки различных расширений. Для начала посмотрите, какие хуки хранятся в репозитории pre-commit/pre-commit-hooks.

Установка

pre-commit написан на Python. По этой причине для его установки рекомендуется использовать PIP. Я советую добавить pre-commit в список зависимостей Python для проекта и установить их в виртуальное окружение.

  1. Добавьте в REQUIREMENTS строку с названием пакета:

    pre-commit
    
  2. Активируйте виртуальное окружение Python:

    source .venv/bin/activate
    
  3. Установите пакеты, указанные в REQUIREMENTS:

    pip install -r REQUIREMENTS
    

Настройка

  1. Создайте в корневом каталоге проекта файл .pre-commit-config.yaml с примерно таким содержимым:

    ---
    repos:
    - repo: https://github.com/pre-commit/pre-commit-hooks
      rev: v4.6.0
      hooks:
        - id: check-yaml
        - id: end-of-file-fixer
        - id: trailing-whitespace
        - id: check-merge-conflict
    

    Примечание: эти настройки я использую для репозитория, в котором хранится исходный код сайта.

  2. Инициализируйте pre-commit и хуки Git:

    git-commit install --install-hooks
    

На этом всё.

Использование

Теперь, когда вы попытаетесь сделать любой коммит в вашем репозитории, будет происходить следующее:

  1. Срабатывание хука Git, запускающего pre-commit.
  2. Запуск обработчиков, необходимые для выполнения настроек, указанных в .pre-commit-config.yaml.

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

Head:     main Update pre-commit settings
Merge:    origin/main Update pre-commit settings

Staged changes (1)
new file  content/posts/0052-pre-commit.md…

Ой!

GitError! Git failed  [Type `$' for details]
Head:     main Update pre-commit settings
Merge:    origin/main Update pre-commit settings

Unstaged changes (1)
modified   content/posts/0052-pre-commit.md…

Staged changes (1)
modified   content/posts/0052-pre-commit.md…

Во время запуска pre-commit файл с этим постом был изменён. По этой причине Git отменил создание коммита. Зато все висячие пробелы были удалены, да и пустая строка в конце файла тоже добавлена. Посмотрим, что там выдал Git (я нажму [$] в буфере magit):

  0 git … add -u -- content/posts/0052-pre-commit.md
  1 git … commit --
check yaml...........................................(no files to check)Skipped
fix end of files.........................................................Passed
trim trailing whitespace.................................................Failed
- hook id: trailing-whitespace
- exit code: 1
- files were modified by this hook

Fixing content/posts/0052-pre-commit.md

check for merge conflicts................................................Passed

Из этого вывода сразу понятно, где споткнулся pre-commit и какие изменения он сделал. Это почти EditorConfig, только от которого нельзя отказаться. Лучше всего эти инструменты работают вместе.

Ещё pre-commit можно запускать без создания коммита. Достаточно добавить файлы в индекс и выполнить команду:

pre-commit run --all