Umieszczanie haków git w repozytorium

197

Czy uważa się to za złą praktykę - umieszczanie .git / hooks w repozytorium projektów (na przykład przy użyciu dowiązań symbolicznych). Jeśli tak, jaki jest najlepszy sposób na dostarczenie tych samych haków różnym użytkownikom git?

shabunc
źródło

Odpowiedzi:

143

Ogólnie zgadzam się z Scytale, z kilkoma dodatkowymi sugestiami, na tyle, że warto osobną odpowiedź.

Najpierw powinieneś napisać skrypt, który utworzy odpowiednie dowiązania symboliczne, szczególnie jeśli te haki dotyczą egzekwowania zasad lub tworzenia przydatnych powiadomień. Ludzie będą o wiele bardziej skłonni do używania haczyków, jeśli będą mogli po prostu pisać, bin/create-hook-symlinksniż jeśli sami to zrobią.

Po drugie, bezpośrednie łączenie haczyków zapobiega dodawaniu własnych haczyków przez użytkowników. Na przykład podoba mi się przykładowy hak wstępnego zatwierdzania, który zapewnia, że ​​nie mam żadnych błędów spacji. Świetnym sposobem na obejście tego jest umieszczenie skryptu opakowującego haczyki w repozytorium i dowiązanie do niego wszystkich haków. Opakowanie może następnie zbadać $0(zakładając, że jest to skrypt bash; odpowiednik jak w argv[0]innym przypadku), aby dowiedzieć się, który hak został wywołany, a następnie wywołać odpowiedni hak w repozytorium, a także hak odpowiedniego użytkownika, którego nazwa będzie musiała zostać zmieniona , przekazując każdemu wszystkie argumenty. Szybki przykład z pamięci:

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

Skrypt instalacyjny przesunąłby wszystkie istniejące zaczepy na bok (dopisał .localdo ich nazw) i dowiązał wszystkie znane nazwy zaczepów do powyższego skryptu:

#!/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
źródło
6
Dodałem chmod +x .git/hooks/*do ciebie, bin/create-hook-symlinks żeby to zrobić.
guneysus
6
@ guneysus Nie powinieneś tego potrzebować, ponieważ haki powinny być już możliwe do wykonania (powinny być w ten sposób sprawdzone), a łącza nie wymagają żadnych specjalnych uprawnień, tylko pliki, do których prowadzą.
Cascabel
13
Lepszym sposobem na zdobycie haka jest reż HOOK_DIR=$(git rev-parse --show-toplevel)/.git/hooks.
Arnold Daniels
2
Stworzyłem
ELLIOTTCABLE
6
Wziąłem tylko to, co niezbędne i umieściłem w repo github.com/sjungwirth/githooks
Scott Jungwirth
111

Nie, umieszczenie ich w repozytorium jest w porządku, sugeruję nawet zrobienie tego (jeśli są one przydatne również dla innych). Użytkownik musi je wyraźnie włączyć (jak powiedziałeś, na przykład poprzez symlinkowanie), co z jednej strony jest trochę uciążliwe, ale z drugiej strony chroni użytkowników przed uruchomieniem dowolnego kodu bez ich zgody.

scy
źródło
13
co jeśli jest to kwestia polityki firmy, to kod nie jest „arbitralny”, to jest wymagany kod, więc byłoby to uważane za ograniczenie w GIT, ponieważ nie ma innego (wstępnie zdefiniowanego) katalogu, który jest śledzony, który również otrzymuje stracony wraz ze zwykłymi hakami
Tobias Hagenbeek
14
Automatyczne dostarczanie haków jest problemem bezpieczeństwa, cieszę się, że Git nie robi tego bezpośrednio - aby egzekwować zasady zespołu / firmy, używać haków po stronie serwera lub pozwolić użytkownikom ręcznie zdecydować się na włączenie ich, jak opisuje @scy :)
Mark K Cowan
4
„chroni użytkowników [...] przed uruchomieniem dowolnego kodu bez ich zgody”. Jeśli programista zrobi tak, jak sugerujesz (dowiązanie symboliczne), wtedy haczyk może zostać zmieniony przez kogoś innego i uruchomić „dowolny kod bez jego zgody”
MiniGod 25.0915
24
MiniGod: Oczywiście. Jeśli jesteś wystarczająco paranoikiem, możesz skopiować haczyki zamiast ich symbolicznie, a następnie poddać je inspekcji i dopiero wtedy włączyć. Jednak większość (potrzebne cytowanie) repozytoria Git będą zawierać kod źródłowy, który ma być uruchomiony na komputerze użytkownika, więc prawdopodobnie i tak będziesz uruchamiać ciągle zmieniający się, niezbadany kod. Ale tak, masz rację. ;)
scy
46

Obecnie można wykonać następujące czynności, aby ustawić katalog, który jest pod kontrolą wersji, aby mieć swój katalog haki git, na przykład, MY_REPO_DIR/.githooksbyłoby

git config --local core.hooksPath .githooks/

Nadal nie można go bezpośrednio wyegzekwować, ale jeśli dodasz notatkę do README (lub cokolwiek innego), wymaga to minimalnego wysiłku ze strony każdego programisty.

barker
źródło
3
Jedną sztuczką, którą znalazłem na viget.com/articles/two-ways-to-share-git-hooks-with-your-team, jest ustawienie opcji z konfiguracji Makefile / CMake / cokolwiek.
Julius Bullinger
6

Ze strony http://git-scm.com/docs/git-init#_template_directory możesz użyć jednego z tych mechanizmów, aby zaktualizować katalog .git / hooks każdego nowo utworzonego repozytorium git:

Katalog szablonów zawiera pliki i katalogi, które zostaną skopiowane do $ GIT_DIR po jego utworzeniu.

Katalog szablonów będzie jednym z następujących (w kolejności):

  • argument podany z opcją --template;

  • zawartość zmiennej środowiskowej $ GIT_TEMPLATE_DIR;

  • zmienna konfiguracyjna init.templateDir; lub

  • domyślny katalog szablonów: / usr / share / git-core / templates.

DavidN
źródło
5

Zapisz w projekcie i zainstaluj w kompilacji

Jak twierdzą inni w swojej odpowiedzi: Jeśli twoje haki są specyficzne dla twoich konkretnych projektów, dołącz je do samego projektu, zarządzanego przez git. Chciałbym pójść jeszcze dalej i powiedzieć, że biorąc pod uwagę, że dobrą praktyką jest budowanie projektu za pomocą jednego skryptu lub polecenia, podczas kompilacji należy zainstalować haki.

Napisałem artykuł o zarządzaniu git hookami , jeśli chcesz przeczytać o tym nieco głębiej.

Java i Maven

Pełne wyłączenie odpowiedzialności; Napisałem wtyczkę Maven opisaną poniżej.

Jeśli zajmujesz się zarządzaniem kompilacją za pomocą Maven dla swoich projektów Java, następująca wtyczka Maven obsługuje instalowanie haków z lokalizacji w twoim projekcie.

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

Umieść wszystkie swoje haki Git w katalogu w swoim projekcie, a następnie skonfiguruj, pom.xmlaby zawierał następującą deklarację wtyczki, cel i konfigurację.

<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>

Po uruchomieniu kompilacji projektu wtyczka skonfiguruje git, aby uruchamiał przechwytywanie z określonego katalogu. To skutecznie ustawi haki w tym katalogu dla wszystkich pracujących nad twoim projektem.

JavaScript i NPM

W przypadku NPM istnieje zależność o nazwie Husky, która pozwala instalować haki, w tym te napisane w JavaScript.

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

Inne

Dodatkowo istnieje wstępne zatwierdzenie dla projektów Python, Overcommit dla projektów Ruby i Lefthook dla projektów Ruby lub Node.

Rudi Kershaw
źródło
1
Dzięki za utworzenie tej wtyczki bardzo ułatwiło to integrację mojego pliku przed zatwierdzeniem.
Michiel Bugher
1

W przypadku projektów PHP opartych na Composer możesz automatycznie dystrybuować je do inżynierów. Oto przykład haków poprzedzających zatwierdzenie i zatwierdzenie msg.

Utwórz hooksfolder, a następnie w pliku 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);\"",
     ],

Następnie możesz je nawet aktualizować, gdy projekt jest kontynuowany, gdy wszyscy są uruchomieni composer install regularnie działają.

Elijah Lynn
źródło
0

Oto skrypt add-git-hook.sh, który można wysłać jako zwykły plik w repozytorium i można go wykonać w celu dołączenia haka git do pliku skryptu. Dostosuj używany hak (pre-commit, post-commit, pre-push itp.) Oraz definicję haka w heredoc kota.

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

Ten skrypt może mieć sens z uprawnieniami do wykonywania lub użytkownik może go uruchomić bezpośrednio. Użyłem tego do automatycznego ściągania git-pull na innych maszynach po popełnieniu.

EDYCJA - odpowiedziałem na łatwiejsze pytanie, które nie było pytaniem i nie było tym, czego szukał OP. Opinie o przypadkach użycia i argumentach dotyczących wysyłania skryptów przechwytujących w repozytorium w porównaniu do zarządzania nimi zewnętrznie w komentarzach poniżej. Mam nadzieję, że to było więcej, czego szukasz.

mathewguest
źródło
Doceniam twój wysiłek i uważam, że jest tu cenna informacja - nie odpowiada ona na zadane pytanie.
shabunc
Moim zdaniem, jeśli haki są specyficzne dla konkretnego repozytorium lub są integralnymi składnikami używanych przepływów pracy, to należą one do repozytorium jako pliki. Trudno je umieścić gdziekolwiek indziej, nie stwarzając więcej problemów niż rozwiązuje. Możesz przechowywać ogólne zaczepy we własnym repozytorium lub na współdzielonym dysku, co może utrzymywać, że repozytorium projektu jest czyste, ale kosztem bycia mniej praktycznym. Zgadzam się z innymi użytkownikami, mówiąc, że haczyki muszą być łatwe do dodania. Dowiązania symboliczne mogą powodować niepotrzebną zależność od konkretnego systemu lub struktury plików.
mathewguest,
Dodatkowo dowiązania symboliczne utrudniają użytkownikom dodawanie własnych haków. Katalog .git / hooks nie jest śledzony, więc źródło powinno zacząć się w repozytorium i przejść do skryptu hooks, a nie na odwrót. Myślę, że kontrargumentem byłoby to, że haczyki git są bardziej związane z przepływem pracy lub zespołem niż projektem, a zatem nie należą do repozytorium. W zależności od konkretnego przypadku użycia, czy lepiej sobie radzisz z potencjalnym zanieczyszczeniem repozytorium git mniej powiązanymi hakami, czy raczej zrezygnowałbyś ze złożoności umieszczenia ich gdzie indziej?
mathewguest,
0

Możesz użyć rozwiązania zarządzanego do zarządzania przechwytem przed zatwierdzeniem, takiego jak zatwierdzenie wstępne . Lub scentralizowane rozwiązanie dla haczyków typu git po stronie serwera, takich jak Datree.io . Ma wbudowane zasady, takie jak:

  1. Wykrywanie i zapobieganie łączeniu się sekretów .
  2. Wymuszaj prawidłową konfigurację użytkownika Git .
  3. Wymuszaj integrację biletu Jira - podaj numer biletu w nazwie żądania ściągnięcia / komunikacie zatwierdzenia.

Nie zastąpi wszystkich twoich haków, ale może pomóc twoim programistom w najbardziej oczywistych, bez konfiguracji konfiguracji instalowania haków na każdym komputerze / repozytorium każdego programisty.

Oświadczenie: Jestem jednym z założycieli Datrees

Shimon Tolts
źródło
3
Myślę, że tworzysz interesujący produkt, ale myślę też, że to nie odpowiada na pytanie i zasadniczo jest autopromocją i niczym więcej.
shabunc