Помещение git hooks в хранилище

197

Считается ли это плохой практикой - помещать .git / hooks в репозиторий проектов (например, используя символические ссылки). Если да, каков наилучший способ доставки одинаковых хуков разным пользователям git?

shabunc
источник

Ответы:

143

Я в целом согласен со Scytale, с парой дополнительных предложений, достаточно того, что стоит отдельного ответа.

Во-первых, вы должны написать скрипт, который создает соответствующие символические ссылки, особенно если эти ловушки связаны с применением политики или созданием полезных уведомлений. Люди будут гораздо чаще использовать крючки, если они могут просто напечататьbin/create-hook-symlinks чем если бы они делали это сами.

Во-вторых, прямые символьные хуки не позволяют пользователям добавлять свои личные хуки. Например, мне скорее нравится пример ловушки перед фиксацией, который гарантирует, что у меня нет ошибок пробелов. Отличный способ обойти это - добавить скрипт репозитория ловушек в репозиторий и поставить с ним ссылку на все ловушки . Оболочка может затем проверить $0(предполагая, что это bash-скрипт; эквивалент, как в argv[0]противном случае), чтобы выяснить, к какому хуку он был вызван, а затем вызвать соответствующий хук в вашем репо, а также хук соответствующего пользователя, который нужно будет переименовать. , передавая все аргументы каждому. Быстрый пример из памяти:

#!/bin/bash
if [ -x $0.local ]; then
    $0.local "$@" || exit $?
fi
if [ -x tracked_hooks/$(basename $0) ]; then
    tracked_hooks/$(basename $0) "$@" || exit $?
fi

Сценарий установки переместит все существующие ранее хуки в сторону (добавит .localк их именам) и объединит все известные имена хуков с вышеуказанным скриптом:

#!/bin/bash
HOOK_NAMES="applypatch-msg pre-applypatch post-applypatch pre-commit prepare-commit-msg commit-msg post-commit pre-rebase post-checkout post-merge pre-receive update post-receive post-update pre-auto-gc"
# assuming the script is in a bin directory, one level into the repo
HOOK_DIR=$(git rev-parse --show-toplevel)/.git/hooks

for hook in $HOOK_NAMES; do
    # If the hook already exists, is executable, and is not a symlink
    if [ ! -h $HOOK_DIR/$hook -a -x $HOOK_DIR/$hook ]; then
        mv $HOOK_DIR/$hook $HOOK_DIR/$hook.local
    fi
    # create the symlink, overwriting the file if it exists
    # probably the only way this would happen is if you're using an old version of git
    # -- back when the sample hooks were not executable, instead of being named ____.sample
    ln -s -f ../../bin/hooks-wrapper $HOOK_DIR/$hook
done
Cascabel
источник
6
Я добавил, chmod +x .git/hooks/*чтобы вы bin/create-hook-symlinks работали.
guneysus
6
@guneysus Вам это не нужно, потому что хуки должны быть уже исполняемыми (они должны быть проверены таким образом), а ссылкам не нужны никакие специальные разрешения, только файлы, на которые они ссылаются.
Каскабель
13
Лучший способ получить DIR - это HOOK_DIR=$(git rev-parse --show-toplevel)/.git/hooks.
Арнольд Дэниелс
2
На этой основе я собрал простую систему для управления хуками в моем проекте: ell.io/tt$Paws.js/blob/Master/Scripts/install-git-hooks.sh
ELLIOTTCABLE
6
Я взял только самое необходимое и поместил его в репозиторий github.com/sjungwirth/githooks
Скотт Джунгвирт
111

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

SCY
источник
13
что если это политика компании, то код не является «произвольным», это обязательный код, так что это будет считаться ограничением в GIT, поскольку отсутствует другой (предварительно определенный) каталог, который отслеживается, который также получает казнен вместе с обычными крючками
Тобиас Хагенбек
14
Автоматическая доставка хуков - это проблема безопасности, я рад, что Git не делает это напрямую - для обеспечения политики команды / компании, использования хуков на стороне сервера или позволяет пользователям вручную включить их, как описывает @scy :)
Марк К Коуэн
4
«защищает пользователей [...] от запуска произвольного кода без их согласия». Если разработчик поступит так, как вы предлагаете (символическая ссылка), то хук может быть изменен кем-то другим, и он может запускать «произвольный код без их согласия»
MiniGod,
24
МиниГод: Конечно. Если вы достаточно параноик, вы можете скопировать хуки вместо символической ссылки, затем проверить их и только потом включить их. Однако большинство репозиториев Git (нужных для цитирования) будут содержать исходный код, который должен быть запущен на компьютере пользователя, поэтому в любом случае вы, вероятно, будете запускать постоянно изменяющийся, неаудированный код. Но да, у вас есть точка. ;)
scy
46

В настоящее время вы можете сделать следующее, чтобы установить каталог, который находится под контролем версии, в качестве вашего каталога git hooks, например, MY_REPO_DIR/.githooksбудет

git config --local core.hooksPath .githooks/

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

bbarker
источник
3
Один трюк, который я нашел на viget.com/articles/two-ways-to-share-git-hooks-with-your-team, заключается в том, чтобы установить опцию из конфигурации Makefile / CMake / чего угодно.
Юлиус Буллингер
6

На http://git-scm.com/docs/git-init#_template_directory вы можете использовать один из этих механизмов для обновления каталога .git / hooks каждого вновь созданного git-репо:

Каталог шаблона содержит файлы и каталоги, которые будут скопированы в $ GIT_DIR после его создания.

Каталог шаблонов будет одним из следующих (по порядку):

  • аргумент, заданный параметром --template;

  • содержимое переменной среды $ GIT_TEMPLATE_DIR;

  • переменная конфигурации init.templateDir; или

  • каталог шаблонов по умолчанию: / usr / share / git-core / templates.

DavidN
источник
5

Хранить в проекте и устанавливать в сборке

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

Я написал статью об управлении git-хуками , если вам интересно почитать об этом чуть подробнее.

Java и Maven

Полный отказ от ответственности; Я написал плагин Maven, описанный ниже.

Если вы управляете сборкой с помощью Maven для своих проектов Java, следующий плагин Maven обрабатывает установку хуков из местоположения в вашем проекте.

https://github.com/rudikershaw/git-build-hook

Поместите все свои ловушки Git в каталог вашего проекта, затем настройте его так, pom.xmlчтобы он включал следующее объявление плагина, цель и конфигурацию.

<build>
  <plugins>
    <plugin>
      <groupId>com.rudikershaw.gitbuildhook</groupId>
      <artifactId>git-build-hook-maven-plugin</artifactId>
      <configuration>
        <gitConfig>
          <!-- The location of the directory you are using to store the Git hooks in your project. -->
          <core.hooksPath>hooks-directory/</core.hooksPath>
        </gitConfig>
      </configuration>
      <executions>
        <execution>
          <goals>       
            <!-- Sets git config specified under configuration > gitConfig. -->
            <goal>configure</goal>
          </goals>
        </execution>
      </executions>
    </plugin>
      <!-- ... etc ... -->
  </plugins>
</build>

Когда вы запустите сборку вашего проекта, плагин настроит git для запуска хуков из указанного каталога. Это эффективно настроит хуки в этом каталоге для всех, кто работает над вашим проектом.

JavaScript и NPM

Для NPM существует зависимость, называемая Husky, которая позволяет устанавливать хуки, в том числе написанные на JavaScript.

// package.json
{
  "husky": {
    "hooks": {
      "pre-commit": "npm test",
      "pre-push": "npm test",
      "...": "..."
    }
  }
}

другие

Кроме того, есть предварительная фиксация для проектов Python, Overcommit для проектов Ruby и Lefthook для проектов Ruby или Node.

Руди Кершоу
источник
1
Спасибо за создание этого плагина, он очень легко интегрировал мой файл предварительной фиксации.
Мишель Бугер
1

Вот скрипт add-git-hook.sh, который вы можете отправить как обычный файл в хранилище и который может быть выполнен для добавления ловушки git к файлу скрипта. Отрегулируйте, какой хук использовать (pre-commit, post-commit, pre-push и т. Д.) И определение хука в cat heredoc.

#!/usr/bin/bash
# Adds the git-hook described below. Appends to the hook file
# if it already exists or creates the file if it does not.
# Note: CWD must be inside target repository

HOOK_DIR=$(git rev-parse --show-toplevel)/.git/hooks
HOOK_FILE="$HOOK_DIR"/post-commit

# Create script file if doesn't exist
if [ ! -e "$HOOK_FILE" ] ; then
        echo '#!/usr/bin/bash' >> "$HOOK_FILE"
        chmod 700 "$HOOK_FILE"
fi

# Append hook code into script
cat >> "$HOOK_FILE" <<EOF

########################################
# ... post-commit hook script here ... #
########################################

EOF

Этот сценарий может иметь смысл иметь разрешения на выполнение или пользователь может запустить его напрямую. Я использовал это для автоматического git-pull на других машинах после фиксации.

РЕДАКТИРОВАТЬ - Я ответил на более простой вопрос, который был не тем, что задавали, и не тем, что искал ОП. В комментариях ниже я остановился на сценариях использования и аргументах для доставки скриптов ловушек в репо, а не на внешнем управлении ими. Надеюсь, это было больше, что вы ищете.

mathewguest
источник
Я ценю ваши усилия и считаю, что здесь есть ценная информация - она ​​не отвечает на поставленный вопрос.
Шабун
На мой взгляд, если хуки являются специфическими для конкретного репозитория или являются неотъемлемыми компонентами используемых рабочих процессов, то они принадлежат репозиторию в виде файлов. Трудно поместить их куда-либо еще, не создавая больше проблем, чем решает. Вы можете хранить общие хуки в своем собственном репозитории или на общем диске, что может поддерживать чистоту в репозитории проекта, но за счет того, что оно гораздо менее практично. Я согласен с другими пользователями в том, что хуки должны легко добавляться. Символические ссылки могут создавать ненужную зависимость от конкретной системы или файловой структуры.
Mathewguest
Кроме того, символические ссылки лишают пользователей возможности добавлять свои собственные хуки. Каталог .git / hooks не отслеживается, поэтому источник должен начинаться с хранилища и переходить в скрипт hooks, а не наоборот. Я думаю, что контраргумент будет заключаться в том, что ловушки git больше связаны с рабочим процессом или командой, а не с проектом, и, следовательно, не принадлежат хранилищу. В зависимости от вашего конкретного сценария использования, вы более склонны к потенциальному загрязнению хранилища git менее связанными хуками или предпочли бы отказаться от множества сложностей при размещении их в другом месте?
Mathewguest
1

Для проектов PHP на основе Composer вы можете автоматически распространять их среди инженеров. Вот пример для ловушек pre-commit и commit-msg.

Создайте hooksпапку, затем в вашем composer.json:

 },
 "scripts": {
     "post-install-cmd": [
         "cp -r 'hooks/' '.git/hooks/'",
         "php -r \"copy('hooks/pre-commit', '.git/hooks/pre-commit');\"",
         "php -r \"copy('hooks/commit-msg', '.git/hooks/commit-msg');\"",
         "php -r \"chmod('.git/hooks/pre-commit', 0777);\"",
         "php -r \"chmod('.git/hooks/commit-msg', 0777);\"",
     ],

Затем вы можете даже обновить их, поскольку проект продолжается, поскольку все работают composer installна регулярной основе.

Элайджа Линн
источник
0

Вы можете использовать управляемое решение для управления хуками перед фиксацией, например, pre-commit . Или централизованное решение для серверных git-хуков, таких как Datree.io . Он имеет встроенные политики, такие как:

  1. Обнаруживать и предотвращать слияние секретов .
  2. Обеспечить правильную настройку пользователя Git .
  3. Обеспечить интеграцию билета Jira - укажите номер билета в названии запроса на получение / сообщении о коммите.

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

Отказ от ответственности: я один из основателей Datrees

Шимон Тольц
источник
3
Я думаю, что вы делаете интересный продукт, но я также думаю, что это не отвечает на вопрос, и в основном это самореклама и ничего более.
Шабун