И избегайте случайных коммитов с личных адресов электронной почты в общедоступных/корпоративных репозиториях Git.

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

# Setup global Git settings (applicable for every repository by default)
git config --global user.name "John Doe"
git config --global user.email  [email protected]
git config --list
# Override global Git settings (applicable for the current project repository only)
cd ~/project/
git config user.name "John Doe"
git config user.email [email protected]
git config --list

К сожалению, иногда разработчики забывают переключиться на правильный профиль git, прежде чем начинать работу с недавно клонированными/созданными репозиториями git, и в конечном итоге используют свои личные адреса электронной почты для коммитов в общедоступных/корпоративных репозиториях git — и наоборот.

Самое простое решение этой проблемы — использовать пользовательский Git Hook для предварительной проверки электронной почты пользователя перед каждым коммитом, и в этом руководстве мы разберемся, как это сделать.

Тем, кто плохо знаком с экосистемой git, рекомендуется понять, как работают git-хуки, прежде чем использовать их (см. часть 1).

Если вы профессионал git, вы можете пропустить часть 1 и сразу перейти к части 2.

Часть 1: Как работают хуки Git [для начинающих]

Git-хуки — это простые скрипты, которые автоматически запускаются в соответствии с набором известных событий жизненного цикла репозитория git.

Например, вы можете настроить git-хук для вызова некоторых предопределенных заданий, нацеленных на жизненный цикл git-коммита (например, pre-commit, prepare-commit-msg).

Расположение Git по умолчанию

Если вы перейдете в каталог .git/hooks любого локального репозитория git, вы можете найти набор примеров хуков, как показано ниже. Если вы удалите часть .sample, эти хуки начнут выполняться по-настоящему, или вы можете отредактировать их и добавить свою собственную логику здесь:

ashen@DevVM:/mnt/d/dev/sample-repo-git-hooks$ ll .git/hooks/
total 28
drwxrwxrwx 1 ashen ashen 4096 Aug 18 23:14 .
drwxrwxrwx 1 ashen ashen 4096 Aug 18 20:38 ..
-rwxrwxrwx 1 ashen ashen  478 Aug 18 20:07 applypatch-msg.sample
-rwxrwxrwx 1 ashen ashen  896 Aug 18 20:07 commit-msg.sample
-rwxrwxrwx 1 ashen ashen  189 Aug 18 20:07 post-update.sample
-rwxrwxrwx 1 ashen ashen  424 Aug 18 20:07 pre-applypatch.sample
-rwxrwxrwx 1 ashen ashen 1642 Aug 18 20:07 pre-commit.sample
-rwxrwxrwx 1 ashen ashen 1239 Aug 18 20:07 prepare-commit-msg.sample
-rwxrwxrwx 1 ashen ashen 1348 Aug 18 20:07 pre-push.sample
-rwxrwxrwx 1 ashen ashen 4898 Aug 18 20:07 pre-rebase.sample
-rwxrwxrwx 1 ashen ashen  544 Aug 18 20:07 pre-receive.sample
-rwxrwxrwx 1 ashen ashen 3610 Aug 18 20:07 update.sample

Если вам интересно, как ваш проект получил эти примеры сценариев, они приходят на ваш компьютер в комплекте с вашей установкой git и находятся внутри /usr/share/git-core/templates/hooks/ местоположения. Каждый раз, когда вы создаете новый репозиторий проекта git (git init) или клонируете существующий (git clone), эти примеры сценариев будут копироваться в папку .git/hooks вашего проекта.

ashen@DevVM:~$ ll /usr/share/git-core/templates/hooks/
total 52
drwxr-xr-x 2 root root 4096 Mar 10 21:00 .
drwxr-xr-x 5 root root 4096 Mar 10 21:00 ..
-rwxr-xr-x 1 root root  478 Apr 20  2020 applypatch-msg.sample
-rwxr-xr-x 1 root root  896 Apr 20  2020 commit-msg.sample
-rwxr-xr-x 1 root root  189 Apr 20  2020 post-update.sample
-rwxr-xr-x 1 root root  424 Apr 20  2020 pre-applypatch.sample
-rwxr-xr-x 1 root root 1642 Apr 20  2020 pre-commit.sample
-rwxr-xr-x 1 root root 1239 Apr 20  2020 prepare-commit-msg.sample
-rwxr-xr-x 1 root root 1348 Apr 20  2020 pre-push.sample
-rwxr-xr-x 1 root root 4898 Apr 20  2020 pre-rebase.sample
-rwxr-xr-x 1 root root  544 Apr 20  2020 pre-receive.sample
-rwxr-xr-x 1 root root 3610 Apr 20  2020 update.sample

Можем ли мы хранить git-хуки централизованно и делиться ими с командой?

Перехватчики Git предназначены для размещения и запуска на машинной основе (т. е. они находятся в частном порядке на машинах клиент/сервер). Это означает, что по умолчанию он не будет добавлен в историю git и не будет помещен в какой-либо центральный репозиторий git, поэтому вы не сможете автоматически делиться этими сценариями со своими коллегами.

Если вы хотите поделиться этими git-хуками со своими коллегами, у вас есть два обходных пути:

1. Отправляйте с репозиторием проекта и настраивайте локально: сохраните git-хуки в новой папке проекта (скажем, .githooks/ или hooks/), зафиксируйте их в истории git и запустите git config --local core.hooksPath hooks/ в своей локальной среде. После этого попросите своих сверстников получить новый запрос/клон и запустить ту же команду в своих локальных средах. Обратите внимание на флаг --local: он означает, что эта конфигурация будет применяться только на уровне вашего локального репозитория проекта и не повлияет на другие репозитории на вашем локальном компьютере.

ashen@DevVM:/mnt/d/dev/sample-repo-git-hooks$ git config --local core.hooksPath hooks/
ashen@DevVM:/mnt/d/dev/sample-repo-git-hooks$ cat .git/config 
[core]
        repositoryformatversion = 0
        filemode = false
        bare = false
        logallrefupdates = true
        ignorecase = true
        hookspath = hooks/
[remote "origin"]
        url = [email protected]:ashen/sample-repo-git-hooks.git
        fetch = +refs/heads/*:refs/remotes/origin/*
[branch "master"]
        remote = origin
        merge = refs/heads/master

2. Отправка с общим репозиторием и глобальная настройка: добавьте git hooks в отдельный общий репозиторий, клонируйте его во всех средах и примените глобально через git config --global core.hooksPath ~/common-tools/hooks/. Этот подход может быть полезен для корпоративных сред, поскольку вы можете применить все политики с помощью единовременной настройки.

ashen@DevVM:~$ git config --global core.hooksPath ~/common-tools/hooks/
ashen@DevVM:~$ cat ~/.gitconfig
[user]
        name = Thilina Ashen Gamage
        email = [email protected]
[http]
        postBuffer = 500M
        maxRequestBuffer = 100M
[core]
        compression = 0
        hooksPath = ~/common-tools/hooks/

Кроме того, вы можете смешать вещи и попробовать свою собственную стратегию.

Примечание. Если у вас более старая версия git (‹2.9), то подход core.hooksPath может быть вам недоступен. В этом случае вы можете попробовать простую символическую ссылку (символическую ссылку), чтобы связать каталог git hooks с .git/hooks местоположением вашего проекта.

# symlink approach
root="$(pwd)"
ln -s "$root/hooks" "$root/.git/hooks"

Чтобы изучить больше возможностей с помощью git hooks, вы также можете прочитать следующие статьи.

Хватит теории… Покажите мне код!

Часть 2. Шаги для предварительной проверки электронной почты пользователя

Теперь давайте вернемся к нашей основной теме — как предварительно проверить адрес электронной почты пользователя перед фиксацией. Вот два подхода, которые вы можете попробовать в зависимости от ваших потребностей:

Пример 1: перехватчик перед фиксацией для отклонения электронных писем пользователей git за пределами домена компании (идеально подходит для локальной конфигурации)

Здесь мы собираемся использовать пользовательский хук pre-commit внутри репозитория нашего проекта.

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

ashen@DevVM:/mnt/d/dev/sample-repo-git-hooks$ git config --local core.hooksPath hooks/
ashen@DevVM:/mnt/d/dev/sample-repo-git-hooks$ git config user.email [email protected]
ashen@DevVM:/mnt/d/dev/sample-repo-git-hooks$ git add change_log.txt && git commit -m "Update change_log"
[ERROR] Invalid email: [email protected] => Please configure the company email and retry.
Steps:
   cd /mnt/d/dev/sample-repo-git-hooks
   git config user.email "<user>@yourcompany.com"

Пример 2: перехватчик перед фиксацией для блокировки электронных писем пользователей git на основе шаблона имени репо и домена электронной почты (идеально подходит для глобальной конфигурации)

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

Попробуем, получится ли.

ashen@DevVM:~$ git config --global core.hooksPath ~/common-tools/hooks/
ashen@DevVM:/mnt/d/dev/company2-services$ git config user.email [email protected]
ashen@DevVM:/mnt/d/dev/company2-services$ git add change_log.txt && git commit -m "Update change_log"
[ERROR] Invalid email: [email protected] => Please configure the company email and retry.
Steps:
   cd /mnt/d/dev/company2-services
   git config user.email "<user>@company2.cloud"

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

Отменить git-хуки

Если вы хотите отменить любой из этих хуков, вы можете использовать команды ниже:

# Unset local/project level git hooks settings
git config --local --unset core.hooksPath
# Unset global level git hooks settings
git config --global --unset core.hooksPath
# Verify changes
git config --list

Заключение

Git-хуки — отличный способ установить политики и автоматизировать некоторые вещи для репозиториев git. В дополнение к сценариям оболочки/bash, упомянутым в приведенных выше примерах, вы даже можете включить код, написанный на других языках, поддерживающих сценарии, которые поддерживает ваша среда (например, Python или JavaScript).

Ожидайте следующих советов по программированию. А пока удачного взлома!