Git-Hooks in das Repository einfügen


197

Wird es als schlechte Praxis angesehen, .git / hooks in das Projekt-Repository zu stellen (z. B. mithilfe von Symlinks). Wenn ja, was ist der beste Weg, um verschiedenen Git-Benutzern dieselben Hooks zu liefern?

Antworten:


143

Ich stimme Scytale im Allgemeinen mit ein paar zusätzlichen Vorschlägen zu, genug, dass es eine separate Antwort wert ist.

Zunächst sollten Sie ein Skript schreiben, das die entsprechenden Symlinks erstellt, insbesondere wenn es bei diesen Hooks darum geht, Richtlinien durchzusetzen oder nützliche Benachrichtigungen zu erstellen. Menschen werden die Haken viel häufiger benutzen, wenn sie nur tippen können, bin/create-hook-symlinksals wenn sie es selbst tun müssen.

Zweitens verhindert das direkte Verknüpfen von Hooks, dass Benutzer ihre eigenen persönlichen Hooks hinzufügen. Zum Beispiel gefällt mir der Beispiel-Pre-Commit-Hook, der sicherstellt, dass ich keine Leerzeichenfehler habe. Eine gute Möglichkeit, dies zu umgehen, besteht darin, ein Hook-Wrapper-Skript in Ihr Repo einzufügen und alle Hooks damit zu verknüpfen. Der Wrapper kann dann untersuchen $0(vorausgesetzt, es handelt sich um ein Bash-Skript; ein Äquivalent wie argv[0]sonst), um herauszufinden, als welcher Hook er aufgerufen wurde, und dann den entsprechenden Hook in Ihrem Repo sowie den Hook des entsprechenden Benutzers aufrufen, der umbenannt werden muss und übergibt alle Argumente an jeden. Schnelles Beispiel aus dem Gedächtnis:

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

Das Installationsskript verschiebt alle bereits vorhandenen Hooks zur Seite ( .localan ihre Namen anhängen ) und verknüpft alle bekannten Hook-Namen mit dem obigen Skript:

#!/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
Ich habe chmod +x .git/hooks/*zu Ihrem hinzugefügt bin/create-hook-symlinks , um es zu arbeiten.
Guneysos

6
@guneysus Das sollten Sie nicht brauchen, da die Hooks bereits ausführbar sein sollten (sie sollten auf diese Weise überprüft werden) und die Links keine besonderen Berechtigungen benötigen, nur die Dateien, auf die sie verlinken.
Cascabel

13
Ein besserer Weg, um das Hook-Verzeichnis zu erhalten, ist HOOK_DIR=$(git rev-parse --show-toplevel)/.git/hooks.
Arnold Daniels

2
Ich habe darauf basierend ein einfaches System zusammengestellt, um die Hooks in meinem Projekt zu verwalten: ell.io/tt$Paws.js/blob/Master/Scripts/install-git-hooks.sh
ELLIOTTCABLE

6
Ich nahm nur das Nötigste und legte es in ein Repo github.com/sjungwirth/githooks
Scott Jungwirth

111

Nein, es ist in Ordnung, sie in das Repository zu stellen. Ich würde sogar vorschlagen, dies zu tun (wenn sie auch für andere nützlich sind). Der Benutzer muss sie explizit aktivieren (wie Sie sagten, zum Beispiel durch Symlinking), was einerseits ein wenig schmerzhaft ist, andererseits Benutzer jedoch davor schützt, beliebigen Code ohne ihre Zustimmung auszuführen.


13
Was ist, wenn es sich um eine Unternehmensrichtlinie handelt, dann ist der Code nicht "willkürlich". Dies ist ein erforderlicher Code. Dies würde als Einschränkung in GIT angesehen, da kein anderes (vordefiniertes) Verzeichnis vorhanden ist, das verfolgt wird und das auch abgerufen wird zusammen mit den regulären Haken ausgeführt
Tobias Hagenbeek

14
Das automatische Bereitstellen von Hooks ist ein Sicherheitsproblem. Ich bin froh, dass Git dies nicht direkt tut - um Team- / Unternehmensrichtlinien durchzusetzen, Hooks auf der Serverseite zu verwenden oder Benutzer manuell entscheiden zu lassen, sie zu aktivieren, wie @scy beschreibt :)
Mark K Cowan

4
"schützt Benutzer [...] davor, beliebigen Code ohne ihre Zustimmung auszuführen". Wenn ein Entwickler möchte, dass Sie vorschlagen (Symlinking), könnte der Hook von jemand anderem geändert werden und "beliebigen Code ohne dessen Zustimmung"
ausführen

24
MiniGod: Natürlich. Wenn Sie ausreichend paranoid sind, können Sie die Hooks kopieren, anstatt sie zu verknüpfen, sie dann prüfen und erst dann aktivieren. Die meisten Git-Repositorys enthalten jedoch Quellcode, der auf dem Computer des Benutzers ausgeführt werden soll, sodass Sie wahrscheinlich ohnehin ständig wechselnden, ungeprüften Code ausführen. Aber ja, du hast Recht. ;)
scy

46

Heutzutage kann man tun , das ein Verzeichnis setzen folgen , die unter Versionskontrolle ist Ihr git Haken Verzeichnis zu sein, zum Beispiel MY_REPO_DIR/.githookswäre

git config --local core.hooksPath .githooks/

Immer noch nicht direkt durchsetzbar, aber wenn Sie eine Notiz in Ihre README-Datei (oder was auch immer) einfügen, erfordert dies ein Minimum an Aufwand seitens jedes Entwicklers.


3
Ein Trick, den ich auf viget.com/articles/two-ways-to-share-git-hooks-with-your-team gefunden habe, besteht darin, die Option in Ihrer Makefile / CMake-Konfiguration / was auch immer festzulegen .
Julius Bullinger

6

Unter http://git-scm.com/docs/git-init#_template_directory können Sie einen dieser Mechanismen verwenden, um das .git / hooks-Verzeichnis jedes neu erstellten Git-Repos zu aktualisieren:

Das Vorlagenverzeichnis enthält Dateien und Verzeichnisse, die nach der Erstellung in das $ GIT_DIR kopiert werden.

Das Vorlagenverzeichnis ist eines der folgenden (in der angegebenen Reihenfolge):

  • das mit der Option --template angegebene Argument;

  • den Inhalt der Umgebungsvariablen $ GIT_TEMPLATE_DIR;

  • die Konfigurationsvariable init.templateDir; oder

  • Das Standardvorlagenverzeichnis: / usr / share / git-core / templates.


5

Im Projekt speichern und im Build installieren

Wie andere in ihrer Antwort angeben: Wenn Ihre Hooks für Ihre speziellen Projekte spezifisch sind, fügen Sie sie in das von git verwaltete Projekt selbst ein. Ich würde dies noch weiter gehen und sagen, dass Ihre Hooks während des Builds installiert werden sollten, da es eine gute Praxis ist, Ihr Projekt mit einem einzigen Skript oder Befehl erstellen zu lassen.

Ich habe einen Artikel über das Verwalten von Git-Hooks geschrieben , wenn Sie daran interessiert sind, etwas ausführlicher darüber zu lesen.

Java & Maven

Vollständiger Haftungsausschluss; Ich habe das unten beschriebene Maven-Plugin geschrieben.

Wenn Sie das Build-Management mit Maven für Ihre Java-Projekte verwalten, übernimmt das folgende Maven-Plugin die Installation von Hooks von einem Ort in Ihrem Projekt.

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

Legen Sie alle Ihre Git-Hooks in einem Verzeichnis in Ihrem Projekt ab und konfigurieren Sie Ihre so pom.xml, dass sie die folgende Plugin-Deklaration, das folgende Ziel und die folgende Konfiguration enthält.

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

Wenn Sie Ihr Projekt erstellen, konfiguriert das Plugin git so, dass Hooks aus dem angegebenen Verzeichnis ausgeführt werden. Dadurch werden die Hooks in diesem Verzeichnis effektiv für alle eingerichtet, die an Ihrem Projekt arbeiten.

JavaScript & NPM

Für NPM gibt es eine Abhängigkeit namens Husky , mit der Sie Hooks installieren können, einschließlich solcher, die in JavaScript geschrieben sind.

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

Andere

Darüber hinaus gibt es Pre-Commit für Python-Projekte, Overcommit für Ruby-Projekte und Lefthook für Ruby- oder Node-Projekte.


1
Vielen Dank, dass Sie dieses Plugin erstellt haben. Dadurch wurde die Integration meiner Pre-Commit-Datei sehr einfach.
Michiel Bugher


1

Bei Composer-basierten PHP-Projekten können Sie diese automatisch an Ingenieure verteilen. Hier ist ein Beispiel für Pre-Commit- und Commit-Msg-Hooks.

Erstellen Sie einen hooksOrdner und dann in Ihrer 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);\"",
     ],

Dann können Sie sie sogar aktualisieren, während das Projekt fortgesetzt wird, da alle composer installregelmäßig ausgeführt werden.


0

Hier ist ein Skript, add-git-hook.sh, das Sie als reguläre Datei im Repository versenden und ausführen können, um den Git-Hook an die Skriptdatei anzuhängen. Passen Sie den zu verwendenden Haken (Pre-Commit, Post-Commit, Pre-Push usw.) und die Definition des Hakens im Cat Heredoc an.

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

Dieses Skript ist möglicherweise sinnvoll, um über ausführbare Berechtigungen zu verfügen, oder der Benutzer kann es direkt ausführen. Ich habe dies verwendet, um nach dem Festschreiben automatisch andere Maschinen zu aktivieren.

BEARBEITEN - Ich beantwortete die einfachere Frage, die nicht gestellt wurde und nach der das OP nicht suchte. Ich habe die Anwendungsfälle und Argumente für den Versand von Hook-Skripten im Repo gegenüber der externen Verwaltung in den Kommentaren unten erläutert. Hoffe das war mehr was du suchst.


Ich schätze Ihre Bemühungen und glaube jedoch, dass es hier wertvolle Informationen gibt - sie beantworten die gestellte Frage nicht.
Shabunc

Wenn die Hooks meiner Meinung nach spezifisch für ein bestimmtes Repository sind oder integrale Bestandteile der verwendeten Workflows sind, gehören sie als Dateien in das Repository. Es ist schwer, sie irgendwo anders zu platzieren, ohne mehr Probleme zu verursachen, als es löst. Sie können allgemeine Hooks in einem eigenen Repository oder auf einem gemeinsam genutzten Laufwerk speichern, wodurch das Projekt-Repo blitzsauber bleibt, jedoch auf Kosten einer viel geringeren Praktikabilität. Ich stimme den anderen Benutzern darin zu, dass die Haken leicht hinzuzufügen sein müssen. Symbolische Verknüpfungen können zu unnötiger Abhängigkeit von einem bestimmten System oder einer bestimmten Dateistruktur führen.
Mathewguest

Darüber hinaus beeinträchtigen symbolische Links die Fähigkeit des Benutzers, eigene Hooks hinzuzufügen. Das Verzeichnis .git / hooks wird nicht nachverfolgt, daher sollte die Quelle im Repository beginnen und in das Hooks-Skript gelangen, nicht umgekehrt. Ich denke, das Gegenargument wäre, dass die Git-Hooks eher mit dem Workflow oder dem Team als mit dem Projekt zusammenhängen und daher nicht in das Repository gehören. Sind Sie abhängig von Ihrem spezifischen Anwendungsfall eher damit einverstanden, das Git-Repository möglicherweise mit weniger verwandten Hooks zu verschmutzen, oder möchten Sie lieber auf eine Menge Komplexität verzichten, wenn Sie sie an einem anderen Ort ablegen?
Mathewguest

0

Sie können eine verwaltete Lösung für die Verwaltung von Hooks vor dem Festschreiben wie Pre-Commit verwenden . Oder eine zentralisierte Lösung für serverseitige Git-Hooks wie Datree.io . Es hat eingebaute Richtlinien wie:

  1. Erkennen und verhindern Sie das Zusammenführen von Geheimnissen .
  2. Erzwingen Sie die richtige Git-Benutzerkonfiguration .
  3. Jira-Ticketintegration erzwingen - Geben Sie die Ticketnummer im Pull-Request-Namen / in der Commit-Nachricht an.

Es wird nicht alle Ihre Hooks ersetzen, aber es könnte Ihren Entwicklern bei den offensichtlichsten helfen, ohne dass die Konfiguration die Hooks auf jedem Entwicklercomputer / Repo installieren muss.

Haftungsausschluss: Ich bin einer der Gründer von Datrees


3
Ich denke, Sie machen ein interessantes Produkt, aber ich denke auch, dass dies die Frage nicht beantwortet und im Grunde eine Eigenwerbung ist und nichts weiter.
Shabunc
Durch die Nutzung unserer Website bestätigen Sie, dass Sie unsere Cookie-Richtlinie und Datenschutzrichtlinie gelesen und verstanden haben.
Licensed under cc by-sa 3.0 with attribution required.