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 server-seitig. Client-seitige Hooks werden durch Operationen wie Commit und Merging ausgelöst, während server-seitige Hooks bei Netzwerkoperationen wie dem Empfangen von Push-Commits ausgeführt werden. Du kannst diese Hooks für die unterschiedlichsten Dinge verwenden.

Einen Hook installieren

Alle Hooks werden im Unterverzeichnis hooks des Git-Verzeichnisses gespeichert. In den meisten Projekten ist das .git/hooks. Wenn du ein neues Repository mit git init einrichtest, füllt Git das hooks-Verzeichnis mit einer Reihe von Beispielskripten, von denen viele für sich allein genommen recht 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. Jedes richtig benannten ausführbaren Skripte sollte funktionieren. Du kannst sie in Ruby oder Python oder einer beliebigen anderen Sprache schreiben, mit der du vertraut bist. Wenn du die mitgelieferten Hook-Skripte verwenden möchtest, musst du sie umbenennen. Ihre Dateinamen enden alle mit .sample.

Füge zum Aktivieren eines Hook-Skripts eine Datei in das hooks Unterverzeichnis deines .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.

Anmerkung

Beachte, dass clientseitige Hooks nicht kopiert werden, wenn du ein Repository klonst. Wenn du mit diesen Skripten beabsichtigen, die Einhaltung einer Richtlinie durchzusetzen, solltest du es auf der Serverseite machen. Sieh dir am Besten 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 du eine Commit-Nachricht eintippen kannst. Er dient dazu, den Snapshot zu untersuchen, der übertragen werden soll. Oder du kannst herausfinden, ob du etwas vergessen hast, um sicherzustellen, dassTests ausgeführt werden oder was immer du im Code überprüfen möchtest. Falls ein Status ungleich Null erkannt wird, bricht der Hook den Commit ab. Du kannst das aber mit git commit --no-verify umgehen. Du kannst verschiedene Optionen ausführen, wie z.B. die Suche nach dem Code Style (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. Du kannst die Standardnachricht bearbeiten, noch bevor der Commit-Autor sie 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. Du kannst es in Verbindung mit einer Commit-Vorlage verwenden, um Informationen automatisiert einzufügen.

Der commit-msg Hook übernimmt einen Parameter, der wiederum den 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. So kannst du deinen Projektstatus oder deine Commit-Beschreibung überprüfen, bevor du einen Commit zulässt. Im letzten Abschnitt dieses Kapitels werden wir demonstrieren, wie du mit diesem Hook überprüfen kannst, ob deine Commit-Beschreibung mit einem vorgegebenen Muster übereinstimmt.

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

E-Mail-Workflow-Hooks

Du kannst drei clientseitige Hooks für einen E-Mail-basierten Workflow einrichten. Alle werden vom git am Befehl aufgerufen, so dass du ohne weiteres zum nächsten Abschnitt springen kannst, wenn du diesen Befehl in deinem Workflow nicht verwendest. Wenn du Patches per E-Mail erhältst, die von git format-patch vorbereitet wurden, dann könnten sich einige davon für dich 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. Du kannst das verwenden, um sicherzugehen, dass eine Commit-Beschreibung korrekt formatiert ist oder um die Nachricht zu normalisieren, indem du sie vom Skript bearbeiten lässt.

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 dir den Snapshot zu untersuchen, bevor du den Commit durchführst. Mit diesem Skript kannst du Tests durchführen oder den Verzeichnisbaum anderweitig durchsuchen. Wenn etwas fehlt oder die Tests nicht erfolgreich waren, 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. Du kannst ihn verwenden, um eine Gruppe oder den Autor des Patches darüber zu informieren, dass du einen Patch gepulled hast. Mit diesem Skript kannst du den Patch-Prozess nicht stoppen.

Andere Client-Hooks

Der pre-rebase Hook läuft, noch bevor du etwas rebased und kann den Prozess stoppen, wenn du ihn mit einem Wert ungleich Null beendest. Du kannst 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 deinem Workflow harmonieren.

Der post-rewrite Hook wird von Befehlen durchgeführt, die Commits ersetzen, wie z.B. git commit --amend und git rebase (allerdings nicht mit git filter-branch). Sein einziges Argument ist 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 du einen erfolgreichen git checkout durchgeführt hast, läuft der post-checkout Hook. Du kannst damit dein Arbeitsverzeichnis für deine Projektumgebung entsprechend einrichten. Dies kann bedeuten, große Binärdateien zu verschieben, für die du keine Quellcodeverwaltung benötigst oder automatisch Dokumentation zu generieren oder etwas in dieser Richtung.

Der post-merge Hook läuft nach einem erfolgreich abgeschlossenen merge Befehl. Damit kannst du Daten im Verzeichnisbaum wiederherstellen, die Git nicht überwachen kann, wie z.B. die Zugriffsrechte. Dieser Hook kann das Vorhandensein von Dateien außerhalb der Git-Kontrolle überprüfen, die du möglicherweise kopieren möchtest, wenn sich der Arbeitsbaum ändert.

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. Du kannst 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 dich darüber zu informieren oder um die Speicherbereinigung abzubrechen, wenn der Zeitpunkt nicht günstig ist.

Serverseitige Hooks

Zusätzlich zu den clientseitigen Hooks kannst du als Systemadministrator einige wichtige serverseitige Hooks verwenden, um nahezu jede Art von Richtlinien für dein 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. So kannst du 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. Du kannst 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. Satt 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 an eine Liste, die Benachrichtigung eines Continuous Integration Servers oder die Aktualisierung eines Ticket-Tracking-Systems. Du kannst 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 mit seiner aktuellen Aktivität fertig ist. Passe daher auf, wenn du eine Aktion durchführst, die sehr lang dauern kann.

Hinweis

Wenn du ein Skript/einen Hook schreibst, den andere lesen sollen, bevorzuge die langen Versionen der Befehlszeilenflags. In sechs Monaten wirst du dafür dankbar sein.

scroll-to-top