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

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

10 ответов

Решение

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

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

git config --local core.hooksPath .githooks/

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

Я в целом согласен со 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

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

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

Java и Maven

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

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

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

<build>
  <plugins>
    <plugin>
      <groupId>com.rudikershaw.gitbuildhook</groupId>
      <artifactId>git-build-hook-maven-plugin</artifactId>
      <version>2.0.1</version>
      <configuration>
        <!-- The locations of a variety of different hooks to install in the local project. -->
        <preCommit>path/to/hook.sh</preCommit>
      </configuration>
      <executions>
        <execution>
          <goals>
            <!-- Inititalise a Git repository if one does not already exist. -->
            <goal>initialize</goal>          
            <!-- Install Git hooks. -->
            <goal>install</goal>
          </goals>
        </execution>
      </executions>
    </plugin>
  <!-- ... etc ... -->
  </plugins>
</build>

JavaScript и NPM

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

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

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

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

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

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

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

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

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

Для проектов 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 на регулярной основе.

https://www.npmjs.com/package/pre-commit npm package обрабатывает это элегантно, позволяя вам указать хуки pre-commit в вашем package.json.

Похоже, что многие сообщения устарели, по крайней мере, если вы используете предварительную фиксацию в экосистеме python (+ я обнаружил, что изменение пути к крючку git не работает с немного более старыми версиями git, например 2.3). С .pre-commit-config.yaml в каталоге hooks в корне вашего репозитория самым простым решением является запуск:

      pre-commit install -f --config hooks/.pre-commit-config.yaml

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

#!/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.

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 на других машинах после фиксации.

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

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

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

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

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

Другие вопросы по тегам