Git
Chapters ▾ 2nd Edition

8.3 Git einrichten - Git Hooks

Git Hooks

Wie viele andere Versionskontrollsysteme hat Git eine Option, um benutzerdefinierte Skripte zu starten, wenn wichtige Ereignisse eintreten. Es gibt zwei Gruppen dieser Hooks: client-seitig und serverseitig. Client-seitige Hooks werden durch Operationen wie Commit und Merging ausgelöst, während serverseitige Hooks bei Netzwerkoperationen wie dem Empfangen von Push-Commits ausgeführt werden. Sie können diese Hooks aus den unterschiedlichsten Gründen verwenden.

Einen Hook installieren

Alle Hooks werden im Unterverzeichnis hooks des Git-Verzeichnisses gespeichert. In den meisten Projekten ist das .git/hooks. Wenn Sie ein neues Repository mit git init einrichten, füllt Git das hooks-Verzeichnis mit einer Reihe von Beispielskripten, von denen viele für sich allein genommen nützlich sind. Sie dokumentieren aber auch die Input-Werte jedes Skripts. Alle Beispiele sind als shell-Skripte verfasst, wobei in einigen Perl eingebaut ist, aber alle richtig benannten ausführbaren Skripte funktionieren gut – Sie können sie in Ruby oder Python oder einer beliebigen anderen Sprache schreiben, mit der Sie vertraut sind. Wenn Sie die mitgelieferten Hook-Skripte verwenden möchten, müssen Sie sie umbenennen. Ihre Dateinamen enden alle mit .sample.

Fügen Sie zum Aktivieren eines Hook-Skripts eine Datei in das hooks Unterverzeichnis Ihres .git-Verzeichnisses ein, die einen passenden Namen trägt (ohne Erweiterung) und ausführbar ist. Ab diesem Zeitpunkt sollte es aufgerufen werden können. Wir werden die meisten wichtigen Hook-Dateinamen hier besprechen.

Clientseitige Hooks

Es gibt viele clientseitige Hooks. Dieser Abschnitt unterteilt sie in Committing-Workflow-Hooks, E-Mail-Workflow-Skripte und alles andere.

Note

Beachten Sie, dass clientseitige Hooks nicht kopiert werden, wenn Sie ein Repository klonen. Wenn Sie mit diesen Skripten beabsichtigen, die Einhaltung einer Richtlinie durchzusetzen, werden Sie das wahrscheinlich auf der Serverseite machen wollen; sehen Sie sich das Beispiel in Beispiel für Git-forcierte Regeln an.

Committing-Workflow Hooks

Die ersten vier Hooks beziehen sich auf den Committing-Prozess.

Als erstes wird der pre-commit Hook ausgeführt, bevor Sie eine Commit-Nachricht eintippen können. Er dient dazu, den Snapshot zu untersuchen, der übertragen werden soll. Sie können herausfinden, ob Sie etwas vergessen haben, ob Tests ausgeführt werden oder was immer Sie im Code überprüfen müssen. Falls ein Status ungleich Null erkannt wird, bricht der Hook den Commit ab. Sie können das aber mit git commit --no-verify umgehen. Sie können verschiedene Optionen ausführen, wie z.B. die Suche nach dem Codestil (lint oder ähnliches ausführen), die Suche nach Leerzeichen am Ende des Textes (der Standard-Hook macht genau das) oder die Suche nach einer geeigneten Dokumentation zu neuen Methoden.

Der prepare-commit-msg Hook wird ausgeführt, bevor der Commit-Message-Editor gestartet wird, aber nachdem die Standardmeldung erstellt wurde. Sie können die Standardnachricht bearbeiten, noch bevor sie der Commit-Autor sieht. Dieser Hook verwendet einige Parameter: den Pfad zur Datei, die die Commit-Nachricht bisher enthält, die Art des Commits und den Commit SHA-1, wenn es sich um einen geänderten Commit handelt. In der Regel ist dieser Hook für normale Commits nicht geeignet. Er ist eher für Commits gedacht, bei denen die Standardnachricht automatisch generiert wird, wie z.B. vordefinierte Commit-Nachrichten, Merge Commits, Squashed Commits und modifizierte Commits. Sie können es in Verbindung mit einer Commit-Vorlage verwenden, um Informationen programmgesteuert einzufügen.

Der commit-msg Hook übernimmt einen Parameter, der wiederum der Pfad zu einer temporären Datei angibt, die die vom Entwickler geschriebene Commit-Beschreibung enthält. Wenn dieses Skript mit Status ungleich Null endet, bricht Git den Commit-Prozess ab, damit Sie Ihren Projektstatus oder Ihre Commit-Beschreibung überprüfen können, bevor Sie einen Commit durchlaufen lassen. Im letzten Abschnitt dieses Kapitels werden wir demonstrieren, wie Sie mit diesen Hook überprüfen können, ob Ihre Commit-Beschreibung mit einem erforderlichen Muster übereinstimmt.

Nachdem der gesamte Commit-Prozess abgeschlossen ist, wird der post-commit Hook gestartet. Er benötigt keine Parameter, aber Sie können den letzten Commit mühelos abrufen, indem Sie git log -1 HEAD aufrufen. Im Allgemeinen wird dieses Skript für Benachrichtigungen oder ähnliches verwendet.

E-Mail-Workflow-Hooks

Sie können drei clientseitige Hooks für einen E-Mail-basierten Workflow einrichten. Alle werden vom git am Befehl aufgerufen, so dass Sie ohne weiteres zum nächsten Abschnitt springen können, wenn Sie diesen Befehl in Ihrem Workflow nicht verwenden. Wenn Sie Patches per E-Mail erhalten, die von git format-patch vorbereitet wurden, dann könnten sich einige davon für Sie als nützlich erweisen.

Der zuerst ausgeführte Hook ist applypatch-msg. Dafür wird ein einziges Argument verwendet: der Name der temporären Datei, die die vorgeschlagene Commit-Beschreibung enthält. Git bricht den Patch ab, wenn der Status dieses Skripts mit ungleich Null endet. Sie können das verwenden, um sicherzugehen, dass eine Commit-Beschreibung korrekt formatiert ist oder um die Nachricht zu normalisieren, indem Sie sie vom Skript bearbeiten lassen.

Der nächste Hook, der beim Anwenden von Patches über git am läuft, ist pre-applypatch. Etwas verwirrend ist, dass er nach dem Einspielen des Patches, aber vor einem Commit ausgeführt wird. Das ermöglicht es Ihnen den Snapshot zu untersuchen, bevor Sie den Commit durchführen. Mit diesem Skript können Sie Tests durchführen oder den Verzeichnisbaum anderweitig durchsuchen. Wenn etwas fehlt oder die Tests nicht bestanden werden, wird das git am Skript durch Exit ungleich Null abgebrochen, ohne den Patch zu übertragen.

Der letzte Hook, der während einer git am Operation läuft, ist post-applypatch, der nach dem Commit ausgeführt wird. Sie können ihn verwenden, um eine Gruppe oder den Autor des Patches, den Sie in den Patch eingefügt haben, darüber zu informieren, dass Sie ihn verwendet haben. Mit diesem Skript können Sie den Patch-Prozess nicht stoppen.

Andere Client-Hooks

Der pre-rebase Hook läuft, noch bevor Sie etwas rebasieren und kann den Prozess stoppen, wenn Sie ihn mit einem Wert ungleich Null beenden. Sie können diesen Hook dazu nutzen, das Rebasing von bereits gepushten Commits zu unterbinden. Der Beispiel-Hook pre-rebase , den Git installiert, macht das, obwohl er einige Voreinstellungen enthält, die möglicherweise nicht mit Ihrem Workflow übereinstimmen.

Der post-rewrite Hook wird mit Befehlen durchgeführt, die Commits ersetzen, wie z.B. git git commit --amend und git rebase (allerdings nicht mit git filter-branch). Sein einziges Argument der Befehl, der das Rewrite ausgelöst hat, und er empfängt eine Liste der Rewrites in stdin. Dieser Hook hat die gleichen Einsatzmöglichkeiten wie post-checkout und post-merge.

Nachdem Sie einen erfolgreichen git checkout durchgeführt haben, läuft der post-checkout Hook. Sie können damit Ihr Arbeitsverzeichnis für Ihre Projektumgebung entsprechend einrichten. Möglicherweise bedeutet das, dass große Binärdateien bewegen müssen, deren Quellcode nicht kontrolliert werden soll, keine automatisch generierte Dokumentation benötigen oder etwas ähnliches.

Der post-merge Hook läuft nach einem erfolgreich abgeschlossenen merge Befehl. Damit können Sie Daten im Verzeichnisbaum wiederherstellen, die Git nicht überwachen kann, wie z.B. die Zugriffsrechte. Dieser Hook kann ebenfalls das Vorliegen von Dateien außerhalb der Git-Kontrolle überprüfen, die bei Änderungen im Verzeichnisbaum kopiert werden sollen.

Der pre-push Hook wird während des git push aufgerufen, nachdem die Remote-Refs aktualisiert wurden, aber noch bevor irgendwelche Objekte übertragen wurden. Er empfängt den Namen und die Position des Remotes als Parameter und eine Liste der zu aktualisierenden Referenzen über stdin. Sie können damit eine Reihe von Referenz-Updates validieren, bevor ein Push stattfindet (ein Exit-Code ungleich Null bricht den Push ab).

Git führt gelegentlich eine automatische Speicherbereinigung (engl. garbage collection) als Teil seiner regulären Funktion durch, indem es git gc --auto aufruft. Der pre-auto-gc Hook wird kurz vor der Garbage Collection aufgerufen und kann verwendet werden, um Sie darüber zu informieren oder um die Speicherbereinigung abzubrechen, wenn der Zeitpunkt nicht günstig ist.

Serverseitige Hooks

Zusätzlich zu den clientseitigen Hooks können Sie als Systemadministrator einige wichtige serverseitige Hooks verwenden, um nahezu jede Art von Richtlinien für Ihr Projekt durchzusetzen. Diese Skripte werden vor und nach dem Push auf dem Server ausgeführt. Die Pre-Hooks können jederzeit durch einen Exit-Code ungleich Null den Push zurückweisen und eine Fehlermeldung an den Client zurücksenden. Sie können so eine beliebig komplexe Push-Richtlinie einrichten.

pre-receive

Das erste Skript, das ausgeführt wird, wenn ein Push von einem Client verarbeitet wird, ist pre-receive. Es wird eine Liste von Referenzen übernommen, die von stdin gepusht werden. Wenn der Exit-Code ungleich Null ist, wird keine von ihnen akzeptiert. Sie können diesen Hook benutzen, um bestimmte Aktionen auszuführen, wie z.B. sicherzustellen, dass keine der aktualisierten Referenzen „non-fast-forwards“ sind oder um die Zugriffskontrolle für alle mit dem Push geänderten Refs und Dateien durchzuführen.

update

Das update Skript ist dem pre-receive Skript sehr ähnlich, nur dass es für jeden Branch einmal ausgeführt wird, den der Pusher versucht zu aktualisieren. Wenn der Pusher versucht, in verschiedene Branches zu pushen, läuft pre-receive nur einmal, während das Update einmal pro Branch läuft, auf den gepusht wird. Statt aus stdin zu lesen, verwendet dieses Skript drei Argumente: den Namen der Referenz (Branch), den SHA-1, auf den die Referenz vor dem Push zeigte und den SHA-1, den der Benutzer zu pushen versucht. Wenn das Aktualisierungsskript den Status ungleich Null (engl. non-zero) ausgibt, wird nur diese Referenz abgelehnt; andere Referenzen können noch aktualisiert werden.

post-receive

Der post-receive Hook wird nach Abschluss des gesamten Prozesses ausgeführt und kann zur Aktualisierung anderer Dienste oder zur Benachrichtigung von Benutzern verwendet werden. Er verwendet die gleichen stdin-Daten wie auch der pre-receive Hook. Beispiele umfassen das Mailen einer Liste, die Benachrichtigung eines Continuous Integration Servers oder die Aktualisierung eines Ticket-Tracking-Systems. Sie können sogar die Commit-Nachrichten analysieren, um zu sehen, ob Tickets geöffnet, geändert oder geschlossen werden müssen. Dieses Skript kann den Push-Prozess nicht stoppen und der Client trennt die Verbindung erst, wenn er abgeschlossen ist. Passen Sie daher auf, wenn Sie eine Aktion durchführen, die sehr lang dauern kann.