Можно ли управлять скриптами Git hook вместе с хранилищем?

337

Мы хотели бы сделать несколько основных скриптов-хуков, которыми мы все можем поделиться - для таких вещей, как предварительное форматирование сообщений коммита. В Git есть скрипты хуков, которые обычно хранятся в <project>/.git/hooks/. Однако эти сценарии не распространяются, когда люди выполняют клонирование, и они не контролируются версией.

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

Пэт Нотц
источник
5
Хороший вопрос Я только хотел бы, чтобы был лучший ответ (без жалоб на @mipadi, я просто хотел бы, чтобы у git был способ сделать это более автоматическим способом - даже если только с опцией, указанной для git clone.)
lindes
Я согласен, @lindes! Но, возможно, ограничить это разделение крючков намеренно? Я полагаю, что для пользователей Windows все будет плохо.
Кристианльм
@kristianlm: Есть разные причины, по которым иногда это может быть грязно ... а также иногда, когда это приятно. Я просто хотел бы, чтобы был какой-то вариант или что-то, что копировало бы крючки. Полагаю, мне просто нужно когда-нибудь проверить код git-core и сделать патч. :) (Или надеяться, что кто-то другой делает ... или жить с обходным путем в ответ Мипади , или что-то в этом роде .)
Линдес
pre-commitделает это легким для хуков предварительной фиксации. Не отвечает на вопрос OP об управлении произвольными перехватчиками git, но перехваты перед фиксацией, вероятно, наиболее часто используются в целях качества кода.
ericsoco

Ответы:

144

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

Чтобы сделать символическую ссылку на * nix, все, что вам нужно сделать, это:

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

используйте, ln -sfесли вы готовы переписать то, что в.git/hooks

mipadi
источник
38
это было нетривиально, поэтому я включил ссылку на то, как правильно символьную ссылку: stackoverflow.com/questions/4592838/…
Дэвид Т.
17
В git версии 2.9 теперь есть опция config для core.hooksPathустановки файла вне .git для ссылки на папку hooks.
Аарон Рабинович
216

В Git 2.9 опция конфигурации core.hooksPathуказывает каталог пользовательских хуков.

Переместите ваши хуки в hooksотслеживаемый каталог в вашем хранилище. Затем настройте каждый экземпляр хранилища на использование отслеживаемого hooksвместо $GIT_DIR/hooks:

git config core.hooksPath hooks

В общем случае путь может быть абсолютным или относительным к каталогу, в котором выполняются хуки (обычно это корень рабочего дерева; см. Раздел ОПИСАНИЕ man githooks).

Макс Шенфилд
источник
15
... и каталог хуков, на который можно указывать, может быть отдельным репозиторием хуков;)
René Link
10
Хорошо, этот параметр конфигурации автоматически устанавливается при выполнении клона git?
Кольцо
4
Как правило, переменные git config не могут быть установлены репозиторием, который вы клонируете. Я думаю, что это предотвращает выполнение произвольного кода. git config контролирует выполнение кода через хуки, имя пользователя в сообщениях коммита и другие важные функции.
Макс Шенфилд
1
Что, если кто-то в команде делает git checkout в другую ветку? Они должны включать его в каждую ветвь ..
Джокерстер
1
Это правда. С другой стороны, если вы обновите хуки в новых коммитах, клонированные репозитории автоматически получат их при работе с ветками, созданными поверх этого коммита. Оба способа имеют свои плюсы и минусы.
Fabb
15

Если ваш проект является проектом JavaScript и вы используете в npmкачестве менеджера пакетов, вы можете использовать shared-git-hooks для принудительного применения githooks npm install.

kilianc
источник
5
Теперь я знаю, кто навязчиво добавил это дерьмо .git/hooks.
gavenkoa
Предупреждение - не поддерживает Windows (если он не запущен от имени администратора в git bash). Простым решением является добавление «preinstall»: «git config core.hooksPath hooks» в качестве сценария в package.json. т.е. где ловушки - это папка, содержащая ваши git-скрипты.
Шейн Гэннон
8

Для пользователей Nodejs простое решение - обновить package.json с помощью

{
  "name": "name",
  "version": "0.0.1",
  ......
  "scripts": {
    "preinstall": "git config core.hooksPath hooks", 

Preinstall будет работать до того

установка npm

и перенаправляет git для поиска хуков внутри каталога. \ hooks (или любого другого имени). Этот каталог должен имитировать . \. Git \ hooks с точки зрения имени файла (за исключением .sample) и структуры.

Представьте, что Maven и другие инструменты сборки будут иметь эквивалент предварительной установки .

Он также должен работать на всех платформах.

Если вам нужна дополнительная информация, смотрите https://www.viget.com/articles/two-ways-to-share-git-hooks-with-your-team/

Шейн Гэннон
источник
5

Что касается git-ловушек , то они .git/hooksвызывают маршрут в скрипт в каталоге проекта githooks.

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

рогоз
источник
5

Большинство современных языков программирования, или, скорее, их инструменты сборки, поддерживают плагины для управления перехватчиками git. Это означает, что все, что вам нужно сделать, - это настроить ваш package.json, pom.xml и т. Д., И у кого-либо из вашей команды не останется иного выбора, кроме как выполнить, если они не изменят файл сборки. Плагин будет добавлять контент в каталог .git для вас.

Примеры:

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

https://github.com/olukyrich/githook-maven-plugin

https://www.npmjs.com/package/git-hooks

yuranos
источник
Я пытался добиться этого в общем виде, чтобы использовать в своих проектах, поэтому я написал этот инструмент: pypi.org/project/hooks4git
Lovato,
3

Мы используем решения Visual Studio (и, следовательно, проекты), которые имеют события до и после сборки. Я добавляю дополнительный проект под названием «GitHookDeployer». Сам проект изменяет файл в событии после сборки. Этот файл настроен для копирования в каталог сборки. Таким образом, проект строится каждый раз и никогда не пропускается. В событии сборки он также гарантирует, что все git-хуки находятся на своих местах.

Обратите внимание, что это не общее решение, так как некоторым проектам, конечно, нечего строить.

Майк де Клерк
источник
2

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

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

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

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

Шимон Тольц
источник
1

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

Как-сделать новый
источник
1

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

Таким образом, вы можете написать код Python или Go для достижения ваших целей и поместить его в папку «ловушки». Это будет работать, но не будет управляться вместе с хранилищем.

Два варианта

а) мультискрипты

Вы можете закодировать свои хуки внутри вашей справки и добавить небольшой фрагмент кода в хуки, чтобы вызвать свой идеальный скрипт, например так:

$ cat .git/hooks/pre-commit
#!/bin/bash
../../hooks/myprecommit.js

б) один сценарий

Более крутой вариант - добавить только один скрипт, чтобы управлять ими всеми, вместо нескольких. Итак, вы создаете hooks / mysuperhook.go и указываете на него все нужные вам крючки.

$ cat .git/hooks/pre-commit
#!/bin/bash
../../hooks/mysuperhook.go $(basename $0)

Параметр предоставит вашему скрипту, какой хук был запущен, и вы можете различить его внутри своего кода. Зачем? Иногда, возможно, вы захотите выполнить одну и ту же проверку для коммита и толчка, например.

А потом?

Затем вы можете захотеть иметь дополнительные функции, такие как:

  • Нажмите крючок вручную, чтобы проверить, все ли в порядке, даже до фиксации или нажатия. Если вы просто позвоните своему сценарию (вариант a или b), то добьетесь цели.
  • Запускайте ловушки для CI, поэтому вам не нужно переписывать те же проверки для CI, это будет, например, просто вызывать триггеры commit и push. То же самое, что и выше, должно решить.
  • Вызовите внешние инструменты, такие как валидатор уценки или валидатор YAML. Вы можете делать системные вызовы и должны обрабатывать STDOUT и STDERR.
  • Убедитесь, что у всех разработчиков есть простой способ установки хуков, поэтому нужно добавить хороший скрипт в репозиторий, чтобы заменить хуки по умолчанию правильными
  • Иметь глобальных помощников, таких как проверка для блокировки коммитов для разработки и мастеринга веток, без необходимости добавлять их в каждый репозиторий. Вы можете решить эту проблему, имея другой репозиторий с глобальными скриптами.

Может ли это быть проще?

Да, есть несколько инструментов, которые помогут вам управлять git-hooks. Каждый из них предназначен для решения проблемы с разных точек зрения, и вам может понадобиться понять все из них, чтобы получить тот, который лучше всего подходит для вас или вашей команды. GitHooks.com предлагает много чтения о подключении и несколько инструментов, доступных сегодня.

На сегодняшний день там перечислены 21 проект с различными стратегиями управления git-хуками. Некоторые делают это только для одного хука, некоторые для определенного языка и так далее.

Один из этих инструментов, написанный мной и предложенный бесплатно как проект с открытым исходным кодом, называется hooks4git . Он написан на Python (потому что он мне нравится), но идея состоит в том, чтобы обрабатывать все элементы, перечисленные выше, в одном файле конфигурации с именем .hooks4git.ini, который находится внутри вашего репозитория и может вызывать любой скрипт, который вы хотите вызвать, на любом языке. ,

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

Lovato
источник
Недавно я опубликовал очень короткую версию, и, по согласованию с модераторами, в ней есть объяснение и краткая ссылка на инструмент, который я написал сам, который, я думаю, может помочь другим разработчикам.
Lovato,
1

Для пользователей Gradle

Я нашел эти сценарии очень полезными для проектов Gradle.

build.gradle

apply from: rootProject.file('gradle/install-git-hooks.gradle')

Gradle / установки-ГИТ-hooks.gradle

tasks.create(name: 'gitExecutableHooks') {
    doLast {
        Runtime.getRuntime().exec("chmod -R +x .git/hooks/");
    }
}
task installGitHooks(type: Copy) {
    from new File(rootProject.rootDir, 'pre-commit')
    into { new File(rootProject.rootDir, '.git/hooks') }
}
gitExecutableHooks.dependsOn installGitHooks
clean.dependsOn gitExecutableHooks

зафиксироваться

.... your pre commit scripts goes here
a3765910
источник