Ein Commit ist schnell gemacht: ein paar Dateien geändert, Tests nicht gestartet, Formatter vergessen – und schon landen kleine Fehler im Repository. Genau hier helfen Git-Hooks: Sie führen automatische Checks direkt bei bestimmten Git-Aktionen aus (z. B. vor einem Commit). Dadurch entstehen weniger „Oops“-Commits, Reviews werden entspannter und CI-Pipelines schlagen seltener erst spät fehl.
Dieser Artikel erklärt, wie Git Hooks funktionieren, welche Hooks im Alltag am meisten bringen und wie ein robustes Setup aussieht, das auch im Team praktikabel bleibt.
Was Git-Hooks sind und wann sie laufen
Git bringt ein Hook-System mit: Das sind ausführbare Skripte, die Git zu definierten Zeitpunkten startet. Beispiele sind „vor dem Commit“, „nach dem Merge“ oder „vor dem Push“. Technisch liegen Hooks im Projekt unter .git/hooks und werden lokal ausgeführt.
Wichtig: Hooks werden standardmäßig nicht automatisch mit dem Repository geteilt. Das schützt vor unerwünschtem Code, bedeutet aber auch: Für Teams braucht es eine Strategie, damit alle die gleichen Checks nutzen.
Typische Einsatzfälle im Alltag
- Formatierung erzwingen (z. B. Prettier/Black), damit Reviews nicht ĂĽber Leerzeichen diskutieren.
- Linter laufen lassen, um offensichtliche Fehler frĂĽh zu finden.
- Tests starten (mindestens schnelle Unit-Tests), bevor Code gepusht wird.
- Commit-Messages prüfen, damit die Historie verständlich bleibt.
Wer schon einmal CI-Fehler durch „vergessene Formatierung“ hatte, merkt schnell: Hooks sind besonders effektiv gegen wiederkehrende Kleinigkeiten.
Die wichtigsten Hooks für Codequalität
Es gibt viele Hook-Typen, aber im Alltag sind nur wenige wirklich relevant. Zwei davon sind oft der größte Hebel: pre-commit und pre-push.
pre-commit: Checken, bevor ein Commit entsteht
Der pre-commit Hook läuft direkt vor dem Erstellen eines Commits. Wenn das Skript mit einem Fehlercode endet, wird der Commit abgebrochen. Das ist ideal, um schnell prüfbare Dinge zu erzwingen: Formatierung, Linting, Dateinamen-Regeln oder das Blockieren von Debug-Ausgaben.
Praxis-Tipp: In pre-commit nur schnelle Checks ausführen. Lange Test-Suites gehören eher in pre-push oder in die CI, sonst umgehen Entwickler:innen den Hook genervt.
pre-push: Mehr Sicherheit, bevor Code das Team erreicht
pre-push läuft vor dem Push zu einem Remote. Hier können ruhig umfangreichere Checks passieren, weil Pushes seltener sind als Commits. Typisch sind: Unit-Tests, Build-Schritte oder das Prüfen, ob der Branch up to date ist.
Wer API-Fehler sauber einordnet, profitiert außerdem davon, dass die Pipeline seltener erst spät bricht. Passend dazu hilft der Überblick zu HTTP-Statuscodes, wenn im Backend Fehlerbehandlung Teil der Tests ist.
commit-msg: Verständliche Commit-Nachrichten erzwingen
Der commit-msg Hook prüft den Commit-Text. Damit lassen sich z. B. Mindestlängen oder ein bestimmtes Format durchsetzen. Das ist besonders hilfreich, wenn im Team Konventionen gelten. Für das „Warum“ und gute Beispiele passt Git Commit Messages schreiben als Ergänzung.
Ein praxistaugliches Setup: Hooks mit einem Tool verteilen
Weil Hooks lokal sind, braucht ein Team eine verlässliche Methode, sie zu installieren. Bewährt ist, Hooks im Repository zu versionieren und bei der Installation automatisch zu aktivieren. In JavaScript-Projekten ist Husky verbreitet; in anderen Stacks gibt es ähnliche Ansätze (oder man nutzt ein eigenes Install-Skript).
Ziel ist ein Setup, das zwei Dinge erfüllt: Die Hooks sind reproduzierbar (alle nutzen dieselben Regeln) und sie sind transparent (niemand führt „heimlich“ etwas aus).
Minimalbeispiel fĂĽr pre-commit und pre-push (Node/Frontend)
Die folgende Idee ist unabhängig vom konkreten Tool: pre-commit formatiert und lintet nur geänderte Dateien; pre-push startet Tests. In der Praxis werden dafür häufig Befehle wie „lint“, „format“ und „test“ aus dem Projekt genutzt.
| Hook | Empfohlene Checks | Warum das sinnvoll ist |
|---|---|---|
| pre-commit | Formatter, Linter (nur geänderte Dateien) | Sehr schnelle Rückmeldung, weniger Review-Rauschen |
| pre-push | Unit-Tests, Build (wenn kurz genug) | Fehler werden vor dem Teilen des Codes abgefangen |
| commit-msg | Format/Regeln fĂĽr Commit-Message | Bessere Historie, leichteres Debugging |
So bleibt das Setup schnell (und wird nicht umgangen)
Hooks bringen nur etwas, wenn sie im Alltag akzeptiert werden. Drei typische Gründe, warum Hooks scheitern: Sie sind zu langsam, sie sind instabil (hängende Tools, plattformspezifische Pfade), oder sie blockieren ohne hilfreiche Fehlermeldung.
Strategie: „schnell lokal, streng in CI“
Ein guter Kompromiss ist: lokal nur die Checks, die in Sekunden fertig sind, und alles Weitere in der CI. So wird der Flow nicht zerstört, aber die Qualität bleibt hoch.
Ein ähnliches Prinzip gilt auch für andere Themen: Bei Konfigurationswerten sollte klar sein, was lokal gilt und was in CI/Produktion. Dazu passt Environment Variables verstehen, falls Hooks z. B. einen Test-DB-Host erwarten.
Hilfreiche Fehlermeldungen statt „exit 1“ ohne Kontext
Wenn ein Hook abbricht, sollte klar sein, was zu tun ist: „Bitte Prettier ausführen“ oder „Tests sind fehlgeschlagen, starte: npm test“. Unklare Abbrüche führen fast automatisch zu Workarounds.
Praktische Schritte fĂĽr ein sauberes Hook-Setup
- Nur Checks wählen, die lokal schnell laufen (Formatter/Linter zuerst).
- pre-commit auf geänderte Dateien begrenzen (statt den ganzen Codebase-Lauf).
- pre-push fĂĽr Tests nutzen, die realistisch in kurzer Zeit durchlaufen.
- Fehlermeldungen konkret formulieren: Was ist kaputt, wie wird es repariert?
- Hooks im Team standardisieren (z. B. ĂĽber ein Tool oder Install-Skript).
- CI trotzdem als letzte Instanz behalten: lokal hilft, CI entscheidet.
Häufige Stolperfallen und wie sie sich vermeiden lassen
„Bei mir läuft es, bei dir nicht“ (Betriebssystem, Shell, Pfade)
Hooks sind Skripte. Unterschiedliche Shells oder Pfad-Konventionen können zu Überraschungen führen. Stabiler ist es, Hooks möglichst über Projekt-Commands laufen zu lassen (z. B. package.json-Skripte) statt über komplexe Shell-Logik.
GroĂźe Repos: Hooks werden langsam
Wenn Formatter oder Linter immer die komplette Codebase prüfen, steigen Laufzeiten schnell. Besser: nur Staged Files (also Dateien, die wirklich committed werden) prüfen. So bleibt der Hook gefühlt „sofort“.
Zu viele Regeln auf einmal
Wenn ein Hook zehn Dinge gleichzeitig erzwingt, ist unklar, was gerade scheitert. Besser ist ein schrittweiser Ausbau: erst Formatierung, dann Linting, dann Tests. So bleibt das Team ruhig und die Akzeptanz hoch.
Entscheidungshilfe: Welche Hooks lohnen sich in welchem Projekt?
- pre-commit
- Gut, wenn: viele kleine Commits, gemischte Team-Erfahrung, häufige Format-Konflikte.
- Weniger wichtig, wenn: sehr kleine Codebase und Formatierung bereits automatisch in der IDE erzwungen wird.
- pre-push
- Gut, wenn: Tests schnell sind und CI-Ausfälle teuer Zeit kosten.
- Vorsicht, wenn: Tests regelmäßig lange dauern (dann lieber nur Smoke-Tests lokal).
- commit-msg
- Gut, wenn: Releases, Changelogs oder Ticket-Bezug ĂĽber Commit-Historie laufen.
- Weniger wichtig, wenn: Commits ohnehin nur per Merge-Commit aus PRs entstehen und dort die Nachricht gesetzt wird.
Wie Hooks zur Team-Routine werden, ohne zu nerven
Hooks sind kein Ersatz für Reviews oder CI, aber sie verschieben die häufigsten Fehler nach links: weg vom „später in der Pipeline“ hin zu „sofort auf dem eigenen Rechner“. Das spart Zeit, weil Feedback schneller kommt und Kontext noch frisch ist.
Damit das klappt, sollten Hooks als Team-Regel verstanden werden: klar dokumentiert, leicht installierbar, mit sinnvollen Standards. Wenn zusätzlich Clean-Code-Prinzipien im Projekt gelten, ergänzen sich beide Ansätze gut. Dazu passt Clean Code in JavaScript für typische Frontend-Projekte.
Kurzer Realitätscheck vor dem Rollout
- Laufen die Hooks auf allen unterstĂĽtzten Betriebssystemen?
- Bleibt pre-commit schnell genug fĂĽr den Alltag?
- Sind Fehlermeldungen konkret und handlungsfähig?
- Gibt es einen einfachen Install-Schritt fĂĽr neue Teammitglieder?
Wenn diese Punkte erfüllt sind, liefern pre-commit und pre-push meist den größten Nutzen – mit sehr wenig zusätzlichem Prozess.

