При code review ты указываешь разработчикам на забытые printf, console.log? С ужасом видишь код с синтаксической ошибкой? Или хочешь разграничить права на работу с ветками (как в Bitbucket), потому что джуниор путает порядок веток при слиянии? Хватит это терпеть! У нас же есть Git и Bash!

git push --force
git push —force
 

Легкий старт с Git hooks

У систем контроля версий есть механизм хуков — скрипты-callback’и, запускаемые Git, когда происходит определенное действие. В некотором смысле это шаблон Observer из ООП.

В качестве действия могут выступать commit, apply patch, merge, push, rebase и другие операции Git. Многие думают, что хук можно использовать только для проверки формата commit message, но их область применения ограничена только твоей ленью и/или фантазией. Примеры в статье написаны для Git, но по аналогии можно сделать и для других систем контроля версий — Subversion, Mercurial, Bazaar.

 

Теория хуков

Хуки бывают двух типов:

  • Клиентские — находятся на машине конечного контрибьютора (developer, lieutenant, dictator). Каждый контрибьютор настраивает хуки только для себя в своей копии существующего репозитория, и они не повлияют на других контрибьюторов. Для того чтобы добавить хук, достаточно изменить файл в директории $PROJECT_DIR/.git/hooks/. Изменение в этой директории не может быть закоммичено и будет влиять только на текущего пользователя. Такие хуки можно игнорировать, используя дополнительный флаг git commit --no-verify.
  • Серверные — хуки, исполняемые угадай где :). Они будут применяться ко всем контрибьюторам проекта.
    Для установки такого хука также достаточно изменить файл в директории $PROJECT_DIR/hooks/, но делать это нужно в удаленном репозитории. Пропустить исполнение таких хуков нельзя. Также при клонировании репозитория не получится выкачать хуки, они останутся на удаленном репозитории.

Писать Git hooks можно на любом скриптовом языке: Python, PHP, Ruby, PowerShell и прочих. В статье будет использован Bash.


Hook уведомляет о результате своего выполнения с помощью кода возврата, и если хук возвращает код, отличный от 0, то исполнение прервется и выполнить операцию (git commit, git push и так далее) не получится.
 

Встроенные хуки

При создании репозитория командой git init также создаются примеры хуков, которые можно посмотреть в одноименной директории.

$ captain@jolly-roger:/PONY/.git/hooks$ ls
applypatch-msg.sample     post-update.sample        pre-commit.sample
pre-rebase.sample         update.sample             commit-msg.sample
pre-applypatch.sample     pre-push.sample           prepare-commit-msg.sample

Для того чтобы начать их использовать, достаточно скопировать интересующий файл, убрав постфикс .sample (cp pre-commit.sample pre-commit), и убедиться, что для него выставлены права на исполнение; если нет — выполняем chmod +x pre-commit.

INFO


Полный список возможных видов hooks можно посмотреть на сайте Git или набрав в командной строке man githooks.
 

Хук слева, хук справа

С теорией разобрались. Самое время попрактиковаться на реальных примерах.

 

Запрет на push в ветку

Начнем с серверного хука с названием pre-receive, который исполняется перед тем, как в удаленном репозитории зафиксируются изменения, когда разработчик делает git push. Если хук отдаст код возврата, отличный от 0, то исполнение прервется и зафиксировать изменения в репозитории не удастся.

Предположим, что на нашем проекте есть люди (джуниоры), которые не должны иметь возможность фиксировать изменения в master-ветке, пока не вникнут в проект.
Чтобы избавить их от соблазна, можно добавить pre-receive hook с проверкой по black-list:

#!/bin/bash

changedBranch=$(git symbolic-ref HEAD | sed -e 's,.*/\(.*\),\1,')
blockedUsers=(junior1 junior2)

if [[ ${blockedUsers[*]} =~ $USER ]]; then
    if [ $changedBranch == "master" ]; then
        echo "You are not allowed commit changes in this branch"
        exit 1
    fi
fi

Код получился достаточно простым. В переменную changedBranch записывается ветка, с которой разработчик хочет произвести изменения. Если имя пользователя находится в массиве blockedUsers, тогда мы возвращаем код возврата 1 и не даем зафиксировать изменения в blessed repository.

По аналогии можно сделать проверку по white-list, когда только у конкретных людей (Release managers) есть возможность фиксировать изменения в master-ветке. Теперь реализовать фичу branch permissions продукта Bitbucket Server ты можешь самостоятельно.

Branch permissions в продукте Bitbucket Server
Branch permissions в продукте Bitbucket Server

INFO


Неслучайно master-ветку нужно защищать от прямого доступа всем желающим. Все популярные branching workflow, будь то gitflow
или GitHub flow, первым постулатом определяют, что master-ветка должна быть всегда готова к релизу на продакшен сервера.
 

printf shall not pass

Многие разработчики по-прежнему отлаживают свои программы, используя технику Print debugging (или, по-научному, Tracing) и часто забывают удалить отладочный код при коммите. Чтобы обезопасить наш blessed repository, можно использовать следующий Git hook (как pre-commit, так и pre-receive):

Продолжение статьи доступно только подписчикам

Вариант 1. Оформи подписку на «Хакер», чтобы читать все статьи на сайте

Подписка позволит тебе в течение указанного срока читать ВСЕ платные материалы сайта, включая эту статью. Мы принимаем оплату банковскими картами, электронными деньгами и переводами со счетов мобильных операторов. Подробнее о подписке

Вариант 2. Купи одну статью

Заинтересовала статья, но нет возможности оплатить подписку? Тогда этот вариант для тебя! Обрати внимание: этот способ покупки доступен только для статей, опубликованных более двух месяцев назад.


Комментарии

Подпишитесь на ][, чтобы участвовать в обсуждении

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

Check Also

Как работает Linux: от нажатия кнопки включения до рабочего стола

Лучший способ понять, как работает операционная система, — это проследить поэтапно ее загр…