W3docs

Git Hooks

Git Hooks erklärt: Skripte, die automatisch im Git-Lebenszyklus laufen, um Lint, Tests und Validierungen durchzuführen. Mit pre-commit-Beispiel.

Was sind Git Hooks

Git Hooks sind Skripte, die Git automatisch ausführt, wenn bestimmte Ereignisse eintreten – Commits, Merges, Pushes und mehr. Sie ermöglichen es, benutzerdefinierte Aktionen in den Git-Lebenszyklus einzubinden: einen Linter vor jedem Commit ausführen, das Format einer Commit-Nachricht prüfen oder einen Push blockieren, wenn die Tests fehlschlagen. Hooks sind das Mittel, mit dem Teams lokal Qualitätsgrenzen durchsetzen, bevor fehlerhafter Code die Maschine verlässt.

Diese Seite behandelt, wo Hooks gespeichert werden, den Unterschied zwischen client- und serverseitigen Hooks, die nützlichsten Hooks mit funktionierenden Beispielen, wie ein Hook eine Operation abbricht, wie man einen Hook umgeht und wie Hooks im Team geteilt werden können.

Git Hooks, die in den Phasen des Commit- und Push-Lebenszyklus ausgelöst werden

Wo Hooks gespeichert werden

Jedes Repository verfügt über ein .git/hooks-Verzeichnis mit Beispielskripten und der Endung .sample. Um einen Hook zu aktivieren, muss eine ausführbare Datei mit dem exakten Namen des Hooks und ohne Erweiterung erstellt werden:

ls .git/hooks
# pre-commit.sample  commit-msg.sample  pre-push.sample ...

Die Endung .sample entfernen (oder die Datei neu anlegen) und sie ausführbar machen:

chmod +x .git/hooks/pre-commit

Ein Hook kann in jeder Sprache geschrieben werden, solange die Datei ausführbar ist und mit einer passenden Shebang-Zeile beginnt (#!/bin/sh, #!/usr/bin/env python3, #!/usr/bin/env node usw.). Git prüft lediglich, ob die Datei exakt nach einem bekannten Hook benannt ist, ausführbar ist und einen Exit-Code zurückgibt.

Clientseitige vs. serverseitige Hooks

  • Clientseitige Hooks laufen auf dem eigenen Rechner bei lokalen Operationen wie Commits und Pushes. Sie eignen sich besonders für Linting und Tests.
  • Serverseitige Hooks (wie pre-receive und post-receive) laufen auf dem Remote-Repository, wenn es einen Push empfängt – nützlich, um Richtlinien zentral durchzusetzen.

Die am häufigsten verwendeten Hooks sind clientseitig:

HookAuslöserTypischer Einsatz
pre-commitBevor ein Commit erstellt wirdLint und Test der gestagten Dateien; Abbruch bei Fehler.
prepare-commit-msgBevor der Nachrichteneditor geöffnet wirdTemplate oder Ticket-Nummer einfügen.
commit-msgNachdem die Nachricht geschrieben wurdeNachrichten-Konvention durchsetzen.
post-commitNachdem ein Commit abgeschlossen wurdeBenachrichtigung senden; kein Einfluss auf den Commit.
pre-pushBevor ein Push gesendet wirdDie gesamte Testsuite als letzte Prüfung ausführen.

Wie ein Hook eine Operation abbricht

Der gesamte Steuerungsmechanismus basiert auf dem Exit-Code. Für einen „pre-"-Hook (pre-commit, pre-push, commit-msg, …):

  • Exit 0 → Der Hook hat die Operation genehmigt, und Git fährt fort.
  • Exit ungleich null → Git bricht die Operation ab. Der Commit wird nicht erstellt oder der Push nicht gesendet.

„Post-"-Hooks (post-commit, post-merge, …) laufen nach dem Abschluss der Aktion, daher wird ihr Exit-Code ignoriert – sie können nichts rückgängig machen. Sie sollten für Benachrichtigungen, nicht für Validierungen verwendet werden.

Ein pre-commit-Beispiel

Dieser pre-commit-Hook führt den Projekt-Linter aus und blockiert den Commit, wenn Probleme gefunden werden. Da sh durch set -e beim fehlgeschlagenen Befehl abbricht, ist keine zusätzliche Prüfung von $? erforderlich:

#!/bin/sh
set -e
echo "Running lint..."
npm run lint

Wenn npm run lint mit einem Nicht-Null-Wert beendet wird, gibt set -e diesen Code weiter und der Commit wird abgebrochen. Falls eine benutzerdefinierte Meldung bevorzugt wird, kann das Ergebnis explizit geprüft werden:

#!/bin/sh
if ! npm run lint; then
  echo "Lint failed — commit aborted. Fix the issues and try again."
  exit 1
fi

Diese Datei als .git/hooks/pre-commit speichern und chmod +x .git/hooks/pre-commit ausführen.

Ein commit-msg-Beispiel

Der commit-msg-Hook erhält ein Argument: den Pfad zu einer temporären Datei, die die vorgeschlagene Nachricht enthält. Diese Datei lesen, validieren und bei einem Nicht-Null-Exit ablehnen. Dieses Beispiel setzt einen Conventional Commits-Stil-Präfix durch:

#!/bin/sh
# $1 is the path to the file containing the commit message
message=$(head -n1 "$1")
pattern='^(feat|fix|docs|style|refactor|test|chore): .+'

if ! echo "$message" | grep -Eq "$pattern"; then
  echo "Commit message must start with feat:, fix:, docs:, etc."
  exit 1
fi

Einen Hook umgehen

Ein Hook ist ein Sicherheitsnetz, keine Wand. Wenn es wirklich nötig ist, die pre-commit- und commit-msg-Hooks für eine Operation zu überspringen, kann --no-verify verwendet werden:

git commit --no-verify -m "WIP: skip checks"
git push --no-verify

Dies sollte sparsam eingesetzt werden – das Umgehen des Linters ist der Weg, auf dem fehlerhafter Code in die Historie gelangt.

Hooks im Team teilen

Da .git/hooks nicht versioniert wird, werden Hooks nicht beim Klonen übertragen. Teams lösen dies, indem Hooks in einem versionierten Verzeichnis gespeichert und Git darauf hingewiesen wird:

git config core.hooksPath .githooks

Nun sucht Git im versionierten .githooks/-Verzeichnis statt in .git/hooks. Die Skripte dort einchecken, ausführbar machen, und jedes Teammitglied erhält sie, nachdem der gleiche git config-Befehl ausgeführt wurde (oder ein Setup-Skript dies übernimmt). Weitere Informationen zum Speichern von Repository-spezifischen Einstellungen finden sich unter Git config.

Tools wie Husky automatisieren genau dies für JavaScript-Projekte und richten gemeinsame Hooks bei der Installation ein. Für Richtlinien, die niemand mit --no-verify umgehen darf, sollten serverseitige Hooks oder Branch-Schutzregeln der Hosting-Plattform verwendet werden, da clientseitige Hooks immer auf dem Rechner des Entwicklers liegen.

Verwandte Themen

  • git commit — der Befehl, um den sich pre-commit- und commit-msg-Hooks drehen.
  • Commits signieren — Autorschaft prüfen, oft in Verbindung mit Hooks eingesetzt.
  • Git config — wo core.hooksPath und andere Einstellungen gespeichert werden.
  • Git alias — Abkürzungen für die Befehle, die Hooks ausführen.

Übungen

Übung
Welche Aussagen über Git Hooks sind korrekt?
Welche Aussagen über Git Hooks sind korrekt?
Was this page helpful?