При 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

Эхо кибервойны. Как NotPetya чуть не потопил крупнейшего морского перевозчика грузов

Российское кибероружие, построенное на утекших у АНБ эксплоитах, маскировалось под вирус-в…