Поміщення гакових гаків у сховище


198

Чи вважається це поганою практикою - розміщувати .git/hooksу сховищах проектів (наприклад, використовуючи символьні посилання). Якщо так, то який найкращий спосіб доставити однакові гачки різним користувачам git?

Відповіді:


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

6
Я додав chmod +x .git/hooks/*до вас, bin/create-hook-symlinks щоб це працювало.
guneysus

6
@guneysus Вам цього не потрібно, оскільки гачки вже мають бути виконаними (їх слід перевірити таким чином), а для посилань не потрібні спеціальні дозволи, лише файли, на які вони посилаються.
Каскабель

13
Кращий спосіб дістати крюк-реж HOOK_DIR=$(git rev-parse --show-toplevel)/.git/hooks.
Арнольд Даніельс

2
Я створив на основі цього просту систему для управління гачками у своєму проекті: ell.io/tt$Paws.js/blob/Master/Scripts/install-git-hooks.sh
ELLIOTTCABLE

6
Я взяв лише найнеобхідніші речі
Скотт Юнгвірт

111

Ні, введення їх у сховище нормально, я б навіть запропонував це зробити (якщо вони будуть корисні і для інших). Користувач має чітко включити їх (як ви вже говорили, наприклад, посиланням), що, з одного боку, болить, але захищає користувачів, з іншого боку, від виконання довільного коду без їх згоди.


13
що, якщо мова йде про політику компанії, тоді код не є "довільним", це потрібний код, тому це вважатиметься обмеженням у GIT, оскільки немає іншого (заздалегідь визначеного) каталогу, який відслідковується, який також отримує виконаний разом зі штатними гачками
Тобіас Хагенбек

14
Автоматична доставка гаків - це проблема безпеки, я радий, що Git робить це не безпосередньо - застосовувати політику команди / компанії, використовувати гачки на стороні сервера або нехай користувачі вручну вирішують включити їх так, як описує @scy :)
Позначити K Cowan

4
"захищає користувачів [...] від запуску довільного коду без їх згоди". Якщо розробник зробив би так, як ви пропонуєте (посилаючись на нього), то гак може бути змінений кимось іншим та запустити "довільний код без їхньої згоди"
MiniGod

24
MiniGod: Звичайно. Якщо ви достатньо параноїдальні, ви можете скопіювати гачки замість того, щоб символізувати їх, а потім перевірити їх і лише потім включити їх. Однак більшість (потрібне цитування) сховищ Git міститимуть вихідний код, який потрібно запустити на машині користувача, тому ви, швидше за все, будете постійно працювати, змінюючи код, який не змінюється. Але так, у вас є пункт. ;)
scy

47

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

git config --local core.hooksPath .githooks/

Це все ще не підлягає виконанню, але якщо ви додасте примітку до свого README (або будь-якого іншого), це вимагає мінімум зусиль з боку кожного розробника.


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 dir кожного новоствореного git repo:

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

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

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

  • вміст змінної середовища $ GIT_TEMPLATE_DIR;

  • змінна конфігурація init.templateDir; або

  • каталог шаблонів за замовчуванням: / usr / share / git-core / шаблони.


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 for Ruby та Lefthook для Ruby або Node.


1
Дякуємо за те, що створили цей плагін, інтегрування мого файлу попереднього фіксації дуже просто.
Міхель Багер


1

Ось сценарій add-git-hook.sh, який ви можете відправляти як звичайний файл у сховище, і його можна виконати, щоб додати git-гак до файлу сценарію. Відрегулюйте, яким гачком користуватися (попереднє скоєння, після вчинення, попереднє натискання тощо) та визначення гачка в гередоці кота.

#!/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 на інших машинах після того, як я здійснив.

EDIT - я відповів на простіше запитання, яке було не те, що було задано, а не те, що шукала ОП. Я подумав про випадки використання та аргументи для доставки скриптів гака в репо, а не для управління ними зовні в коментарях нижче. Сподіваюся, що це було більше, що ви шукаєте.


Я вдячний за ваші зусилля і вважаю, що тут є цінна інформація - вона не відповідає на подане запитання.
shabunc

На мою думку, якщо гачки характерні для певного сховища або є невід’ємними компонентами використовуваних робочих процесів, вони належать у сховищі як файли. Важко їх розмістити деінде, не створюючи більше проблем, ніж це вирішує. Ви можете зберігати загальні гачки у власному сховищі або на спільному диску, що може підтримувати проектний репо-писк чистою, але ціною бути набагато менш практичною. Я погоджуюся з іншими користувачами, кажучи, що гачки потрібно легко додати. Символічні посилання можуть створити непотрібну залежність від певної системи чи файлової структури.
mathewguest

Крім того, символічні посилання порушують можливість користувачів додавати власні гачки. Каталог .git / hooks не відслідковується, тому джерело повинно починатись у сховищі та робити його в сценарій гаків, а не навпаки. Я думаю, що контраргументом було б те, що гачки git більше пов'язані з робочим процесом або командою, а не проектом, і тому не належать до сховища. Залежно від конкретного випадку використання, вам більше добре, що потенційно забруднюєте сховище git менш пов’язаними гачками або ви б скоріше відмовилися від кучки складності, якщо розмістити їх де-небудь ще?
mathewguest

1

Для проектів PHP на основі композиторів ви можете автоматично поширювати інженерів. Ось приклад для гачок попередньої фіксації та фіксації 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

Ви можете використовувати кероване рішення для керування гачками, які попередньо здійснюють, як - от попереднє вчинення . Або централізоване рішення для git-гаків на стороні сервера, таких як Datree.io . Він має вбудовані політики, такі як:

  1. Виявлення та запобігання злиття секретів .
  2. Забезпечте належну конфігурацію користувача Git .
  3. Примусово інтеграції квитків Jira - Згадка номер квитка на ім'я запиту тягнути / повідомлення фіксації.

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

Відмова: Я один із засновників Datrees


3
Я думаю, ви робите цікавий продукт, але я також думаю, що це не дає відповіді на питання, і в основному це самореклама і нічого більше.
shabunc
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.