Keine Werbung mögen? Gehen Werbefrei Heute

Git-Hooks Vor-Commit, Vor-Push und Verhinderung schlechter Code an der Tür

Aktualisiert am

Die Hook-Dateien pre-commit, commit-msg und pre-push sind Shell-Skripte, die vor der Ausführung eines Commits oder der Übertragung eines Pushs durch Git ausgeführt werden. Hier erfahren Sie, wie Sie diese Hook-Dateien einrichten, um Fehlern bei der Codeprüfung, schlechten Commit-Messages und verlorenen Geheimnissen zu erkennen – mit echten Beispielen, die Sie heute direkt verwenden können.

Git Hooks: Pre-commit, Pre-push, und das Stoppen schlechter Code an der Tür 1
ANZEIGE Entfernen?

Git bietet Hooks – Shell-Skripte, die an bestimmten Punkten im Arbeitsablauf ausgelöst werden. Die meisten Repos haben sie inaktiv in .git/hooks/ as .sample Dateien. Die meisten Entwickler ignorieren sie, bis ein fehlerhafter Commit oder ein verlorengegangener API-Schlüssel sie dazu bringen, dass sie sich gewünscht haben.

Dies bezieht sich auf die drei Hooks, die auf jedem Projekt konfiguriert werden sollten: pre-commit, commit-msgund pre-push. Jeder davon fängt eine andere Art von Fehler ab. Jeder ist ein Shell-Skript, das Sie heute einfach einfügen und verwenden können.

Wo Hooks leben

Jedes Git-Repository hat einen .git/hooks/ Ordner. Führen Sie ls .git/hooks/ aus und Sie sehen Beispiel-Dateien. Git ignoriert alles mit dem .sample Suffix. Um einen Hook zu aktivieren, entfernen Sie das Suffix und machen ihn ausführbar:

cp .git/hooks/pre-commit.sample .git/hooks/pre-commit
chmod +x .git/hooks/pre-commit

Die Vereinbarung ist einfach: Beenden Sie mit 0 und Git fährt fort. Beenden Sie mit einem anderen Wert und Git wird abgebrochen und gibt alles aus, was Sie an stderr geschrieben haben.

pre-commit: Ihr wertvollster Hook

Pre-commit führt nach dem Tippen von git commit aber vor dem Schreiben des Commit-Objekts. Es sieht nicht das Commit-Meldung – diese wird noch nicht geschrieben. Was es kann tut, ist die geprüften Dateien zu überprüfen und abzubrechen, wenn etwas falsch aussieht.

Das entscheidende Detail: Verwenden Sie git diff --cached --name-only um nur die Dateien zu erhalten, die tatsächlich gestappt wurden. Eine vollständige Projekt-Prüfung bei jedem Commit ist langsam und zeigt Probleme auf, die Sie nicht eingeführt haben.

Linter-Beispiel (ESLint)

#!/bin/sh
# Lint only staged JS files
STAGED_FILES=$(git diff --cached --name-only --diff-filter=ACM | grep '\.js$')

if [ -z "$STAGED_FILES" ]; then
  exit 0
fi

echo "Running ESLint on staged files..."
echo "$STAGED_FILES" | xargs ./node_modules/.bin/eslint

if [ $? -ne 0 ]; then
  echo "ESLint failed. Fix errors before committing."
  exit 1
fi

exit 0

Der --diff-filter=ACM Flag überspringt gelöschte Dateien – es macht keinen Sinn, etwas zu prüfen, das Sie gerade gelöscht haben.

Geheimes Scanning-Beispiel

Ein direkter Muster-Scan, der offensichtliche Fehler erfasst – festgelegte API-Schlüssel, Passwörter in Konfigurationsdateien, die versehentlich eingegeben wurden:

#!/bin/sh
# Block commits with obvious secrets
PATTERNS="(AWS_SECRET|api_key\s*=|password\s*=|PRIVATE KEY)"

if git diff --cached | grep -qiP "$PATTERNS"; then
  echo "Potential secret detected in staged changes. Aborting commit."
  exit 1
fi

exit 0

Für Projekte außerhalb des Spielraums, kombinieren Sie dies mit einem dedizierten Scanner. detect-secrets von Yelp eignet sich gut als pre-commit-Hook – es behält eine Grundlage-Datei, damit bestehende markierte Strings nicht jeden Commit blockieren. trufflehog eignet sich besser für die Analyse der Geschichte nachträglich oder für die Ausführung in CI.

commit-msg: Formatierung der Nachricht erzwingen

Dieser Hook erhält ein Argument: den Pfad zu einer temporären Datei mit Ihrer Entwurf-Commit-Meldung. Lesen Sie es, validieren Sie es und beenden Sie mit 1, um es abzulehnen. Die Datei ist lesbar – Sie können die Meldung normalisieren, anstatt sie abzulehnen, obwohl das die ersten Benutzer überrascht.

Erzwingen von Conventional Commits Format ist die häufigste Anwendung. Die Vorteile sind automatische Änderungslogs, lesbare git log Ausgabe und CI-Pipelines, die auf Commit-Typen prüfen, um zu entscheiden, was veröffentlicht wird:

#!/bin/sh
COMMIT_MSG_FILE=$1
COMMIT_MSG=$(cat "$COMMIT_MSG_FILE")

# type(scope): description — scope is optional
PATTERN="^(feat|fix|chore|docs|style|refactor|test|perf|ci|build|revert)(\(.+\))?: .{1,72}"

if ! echo "$COMMIT_MSG" | grep -qP "$PATTERN"; then
  echo ""
  echo "Invalid commit message. Use Conventional Commits format:"
  echo "  type(scope): short description"
  echo ""
  echo "Valid types: feat, fix, chore, docs, style, refactor, test, perf, ci, build, revert"
  echo "Example:     feat(auth): add OAuth2 login flow"
  echo ""
  echo "Your message: $COMMIT_MSG"
  exit 1
fi

exit 0

Dies erfasst nicht eine gültig formatierte Meldung, die dennoch sinnlos ist wie fix: fix things. Das ist ein Kulturproblem, nicht ein Tooling-Problem.

pre-push: Die letzte Tür vor dem Origin

Pre-push wird ausgelöst nach dem Aufruf von git push aber vor dem Versenden von Daten an die Ferne. Es erhält den Remote-Namen und die URL über stdin. Hier gehören Tests – nicht ein Linter (der in pre-commit läuft), sondern tatsächliche Tests, die das Verhalten überprüfen.

#!/bin/sh
echo "Running tests before push..."

npm test

if [ $? -ne 0 ]; then
  echo "Tests failed. Push aborted."
  exit 1
fi

exit 0

Eine harte Wahrheit: Wenn Ihr Test-Set mehr als 60–90 Sekunden dauert, werden die Menschen --no-verifyverwenden. Führen Sie hier nur schnelle Einheitstests aus. Integration und E2E-Tests gehören in CI, wo eine langsame Ausführung akzeptabel ist. Ein Hook, der langsam genug ist, um übersprungen zu werden, ist schlimmer als kein Hook.

Überspringen von Hooks – und wann das in Ordnung ist

git commit --no-verify
git push --no-verify

Beide Flags existieren aus einem Grund. Ein defekter Hook, der einen Hotfix blockiert, ist das Art von Dinge, das eine gesamte Team gegen Git-Hooks als Konzept verändert. Verwenden Sie --no-verify wenn Sie einen legitimen Grund haben: ein Hook, der auf unveränderten Dateien fehlerhaft ist, oder eine Notfall-Situation, bei der die Lösung wichtiger ist als die Tür.

Wenn Sie es regelmäßig benötigen, müssen die Hooks angepasst werden. Die häufigsten Ursachen: zu langsame Ausführung, Fehlern bei Dateien, die nicht geändert wurden, oder falsche Muster-Matching, die Sie noch nicht bereinigt haben.

Teilen von Hooks mit Ihrem Team

.git/hooks/ ist lokal auf jedes Clone beschränkt – es wird absichtlich nicht in das Repository eingebunden. Zwei Ansätze, um Hooks zu halten:

Option 1: core.hooksPath

Speichern Sie Hooks in einem eingebundenen Ordner (z. B. .githooks/), und zeigen Sie Git darauf hin:

git config core.hooksPath .githooks

Um dies für neue Clones automatisch vorzunehmen, fügen Sie einen prepare Skript in package.json ein – npm führt es automatisch bei npm install:

{
  "scripts": {
    "prepare": "git config core.hooksPath .githooks"
  }
}

Machen Sie die Skripte ausführbar, commiten Sie sie und jeder, der klonen und npm install ausführt, erhält automatisch die konfigurierten Hooks.

Option 2: Husky

Husky ist die Standardwahl für JavaScript/Node-Projekte. Es übernimmt die core.hooksPath Verkabelung für Sie und gibt jedem Hook eine eigene Datei in .husky/:

npx husky init

Dann fügen Sie Hooks als einfache Shell-Skripte hinzu:

echo "npm test" > .husky/pre-push
chmod +x .husky/pre-push

Husky 9 (im Frühjahr 2024 veröffentlicht) hat die JSON-Konfig vollständig abgeschafft und stattdessen nur bare Shell-Skripte verwendet. Einfacher als v4/v8 für neue Einrichtungen, aber das Migration von Husky 4 ist ein bruchendes Änderung, die offizielle Migrationsguides unterschätzen – das alte .huskyrc Format funktioniert nicht mehr. Wenn Sie ein bestehendes Repository aktualisieren, planen Sie dafür Zeit ein.

Nicht-JavaScript-Repositories werden besser durch die core.hooksPath Ansatz bedient. Es gibt keinen Grund, eine Node-Abhängigkeit nur für Hook-Verwaltung einzubinden.

Überprüfen Sie Ihren Diff vor dem Ausführen des Hooks

git diff --cached zeigt die geplanten Änderungen im Terminal. Wenn Sie zwei Versionen einer Konfigurationsdatei vergleichen oder prüfen, was eine Refactoring tatsächlich über mehrere Bearbeitungen geändert hat, ist ein visueller Diff schneller zu scannen. IO Tools’ Text Diff erlaubt es Ihnen, zwei Versionen einzufügen und genau zu sehen, was sich geändert hat – nützlich, wenn Sie prüfen wollen, was in einen Commit eingefügt wird, bevor Hooks ausgeführt werden.

Git-Hooks sind eine der wenigen Automatisierungswerkzeuge, die vollständig in Ihrem bestehenden Workflow leben – ohne CI-Konto, ohne zusätzlichen Dienst, ohne Kosten. Ein pre-commit-Hook, der eine Lint-Fehler ablehnt, ist genauso zuverlässig wie das Shell-Skript, das Sie geschrieben haben. Das ist ein Feature: Sie können es in einer Minute lesen, debuggen und ändern. Konfigurieren Sie die drei Hooks oben und Sie haben die häufigsten Lücken zwischen „es funktioniert lokal“ und „es funktioniert auf main“ geschlossen.

Möchten Sie werbefrei genießen? Werde noch heute werbefrei

Erweiterungen installieren

IO-Tools zu Ihrem Lieblingsbrowser hinzufügen für sofortigen Zugriff und schnellere Suche

Zu Chrome-Erweiterung Zu Kantenerweiterung Zu Firefox-Erweiterung Zu Opera-Erweiterung

Die Anzeigetafel ist eingetroffen!

Anzeigetafel ist eine unterhaltsame Möglichkeit, Ihre Spiele zu verfolgen. Alle Daten werden in Ihrem Browser gespeichert. Weitere Funktionen folgen in Kürze!

ANZEIGE Entfernen?
ANZEIGE Entfernen?
ANZEIGE Entfernen?

Nachrichtenecke mit technischen Highlights

Beteiligen Sie sich

Helfen Sie uns, weiterhin wertvolle kostenlose Tools bereitzustellen

Kauf mir einen Kaffee
ANZEIGE Entfernen?