Implementieren von Git-Hooks

Abgeschlossen

Die Priorisierung der Codequalität im Entwicklungsprozess sollte mit der lokalen Codeentwicklung beginnen. Es ist wichtig, Chancen für diese Praxis zu identifizieren, auch bevor Pull Requests gestartet werden, um potenzielle Codequalitätsprobleme zu erkennen und zu beheben.

Git Hooks bieten eine großartige Gelegenheit dafür. Sie dienen als Mechanismus zum Ausführen von benutzerdefinierten Skripts als Reaktion auf wichtige Ereignisse innerhalb des Git-Lebenszyklus, z. B. Commits, Merges und Pushes. Die Skripte, die sich im Verzeichnis .git\hooks des Repositorys befinden, bieten praktisch unbegrenzte Flexibilität bei der Automatisierung von Softwareentwicklungsaufgaben und der Durchsetzung von Entwicklungsstandards.

Implementieren von Git Hooks

Sehen wir uns zunächst clientseitige Git-Hooks an. Navigieren Sie zum Verzeichnis .git\hooks im Repository – dort finden Sie viele Dateien mit der Erweiterung sample. Diese Erweiterung gibt nicht nur ihren Zweck an, sondern verhindert auch effektiv, dass sie ausgeführt werden. Die Dateinamen geben die Git-Aktionen an, die die Ausführung auslösen, sobald Sie die Erweiterung sample entfernen.

Screenshot: GitHub-Hookdateien für Automatisierung.

Benennen Sie die pre-commit-Datei sample in „pre-commit“ um. Wie der Name der Datei schon sagt, wird das darin enthaltene Skript immer dann ausgeführt, wenn Sie die Aktion „git commit“ aufrufen. Der Commit folgt nur, wenn das pre-commit-Skript mit dem Rückgabewert 0 beendet wird.

Sie sollten jedoch beachten, dass dies in keinem der Windows-Betriebssysteme standardmäßig wie vorgesehen funktioniert. Der häufig übersehene Grund für dieses Verhalten ist die erste Zeile des Skripts:

#!/bin/sh

Auf Linux-Betriebssystemen zeigt das Präfix #! dem Programmlader an, dass der Rest der Datei ein zu interpretierendes Skript enthält und /bin/sh der vollständige Pfad zum Interpreter ist, der verwendet werden soll.

Git für Windows unterstützt zwar Bash-Befehle und Shellskripts, folgt aber nicht der gleichen Konvention bei der Angabe von Dateisystempfaden. Stattdessen müssen Sie den vollständigen Pfad zur Datei sh.exe angeben, beginnend mit dem Laufwerksbuchstaben.

Es gibt jedoch eine zusätzliche Einschränkung, die sich aus der Tatsache ergibt, dass Git für Windows standardmäßig im Verzeichnis „C:\Programme“ installiert wird. Da dieses Verzeichnis ein Leerzeichen in seinem Namen enthält, wird der resultierende Pfad zur sh.exe Datei als zwei separate Pfade interpretiert, was zu einem Fehler führt. Um dies zu vermeiden, müssen Sie vor dem Leerzeichen einen einzelnen umgekehrten Schrägstrich (\) als Escapezeichen hinzufügen. Wenn Sie die 64-Bit-Version von Git für Windows verwenden, sollte die erste Zeile des Skripts das folgende Format aufweisen:

#!C:/Program\ Files/Git/usr/bin/sh.exe

Vorgehensweise

Wie können Sie die neu ermittelte Funktionalität von pre-commit Git-Skripts verwenden? Wie können Sie verhindern, dass Sie versehentlich geheime Schlüssel an GitHub weitergeben?

Verwenden wir den Git Hook, um den Code, der in Ihr lokales Repository übertragen wird, nach bestimmten Schlüsselwörtern zu durchsuchen. Ersetzen Sie den Inhalt in der „pre-commit“-Shelldatei durch den folgenden Code:

#!C:/Program\ Files/Git/usr/bin/sh.exe
matches=$(git diff-index --patch HEAD | grep '^+' | grep -Pi 'password|secret')
if [ ! -z "$matches" ]
then
  cat <<\EOT
Error: Words from the blocked list were present in the diff:
EOT
echo $matches
exit 1
fi

Dieses Beispiel soll das Konzept veranschaulichen und keine vollständigen Lösung darstellen, daher ist die Schlüsselwortliste absichtlich trivial. Mit regulären Ausdrücken können Sie den Bereich und die Flexibilität erheblich erweitern. Sie haben auch die Möglichkeit, auf eine externe Datei zu verweisen, was die kontinuierliche Pflege erheblich vereinfachen würde.

Ein Blick hinter die Kulissen

Nach dem Aufruf verwendet das pre-commit Hook-Skript die Befehle git diff und grep, um Schlüsselwörter oder Muster in den inkrementellen Änderungen des Codes zu identifizieren, die übertragen werden. Wenn Übereinstimmungen erkannt werden, generiert das Skript eine Fehlermeldung und verhindert, dass der Commit ausgeführt wird.

Es gibt noch mehr:

Weitere gängige Anwendungsfälle von pre-commit Hook-Skripts umfassen Codeformatierung, Linting oder das Ausführen benutzerdefinierter Tests, um sicherzustellen, dass der Commit den Projektstandards entspricht. Prepare-commit-msg wird ausgeführt, bevor der Editor für die Commit-Nachricht gestartet wird. Es ermöglicht die dynamische Erstellung von Commit-Nachrichten, um Namenskonventionen durchzusetzen, wie z.B. die Verwendung von bestimmten Präfixen (z. B. feat: für Features oder fix: für Bugfixes).

Das folgende Skript prepare-commit-msg zum Beispiel stellt der Commit-Nachricht automatisch den Namen des aktuellen Branches voran, wenn Sie einen neuen Commit erstellen. Es ändert die Commit-Nachrichtendatei ($1), indem es den Namen des Branchs gefolgt von einem Doppelpunkt und einem Leerzeichen am Anfang der Datei hinzufügt.

#!C:/Program\ Files/Git/usr/bin/sh.exe
# Get the current branch name
branch_name=$(git branch --show-current)
# Check if the commit message file exists
if [[ -f "$1" ]]; then
  # Prepend the branch name to the commit message
  sed -i "1s/^/$branch_name: /" "$1"
fi

Post-commit Skripts werden nach Abschluss des Commits ausgeführt. Sie können verwendet werden, um Benachrichtigungen auszulösen oder Dokumentationen zu generieren.

Das folgende Skript sendet beispielsweise nach jedem Commit eine E-Mail-Benachrichtigung an eine bestimmte Empfängerin oder einen bestimmten Empfänger. Sie können das Skript anpassen, indem Sie die Empfänger-E-Mail-Adresse, der SMTP-Server und der Betreff und der Textkörper der E-Mail ändern. Darüber hinaus müssen Sie ihr System möglicherweise so konfigurieren, dass E-Mails mithilfe des PowerShell-Cmdlets „Send-MailMessage“ gesendet werden, oder je nach Umgebung und Anforderungen eine andere Methode zum Senden von Benachrichtigungen verwenden.

#!C:/Program\ Files/Git/usr/bin/sh.exe
# Set the recipient email address
$recipient="your@email.com"
# Set the subject of the email
$subject="Git Commit Notification"
# Set the body of the email
$body="A new commit has been made to the repository."
# Send the email notification
Send-MailMessage -To $recipient -Subject $subject -Body $body -SmtpServer "your.smtp.server"

Der Ordner „.git\hooks“ im Repository wird nicht in die Quellcodeverwaltung committet. Sie fragen sich vielleicht, ob es eine Möglichkeit gibt, die Skripts, die Sie mit anderen Teammitgliedern entwickelt haben, zu teilen. Die gute Nachricht ist, dass Sie ab Git Version 2.9 Git-Hooks einem Ordner zuordnen können, der in die Quellcodeverwaltung committet werden kann. Hierzu könnten Sie die Konfiguration der globalen Einstellungen für Ihr Git-Repository aktualisieren:

Git config --global core.hooksPath '~/.githooks'

Wenn Sie die Git-Hooks jemals überschreiben müssen, haben Sie sie auf der Clientseite eingerichtet und können dies durch Verwendung des Schalters „no-verify“ erreichen:

Git commit --no-verify

Serverseitige Hooks

Während clientseitige Git Hooks robuste Funktionen zur Verbesserung des Entwicklungsworkflows bieten, bietet Azure Repos auch serverseitige Hooks, um den Entwicklungsprozess zu verbessern, einschließlich der Unterstützung für das Erstellen von Pull Requests. Weitere Informationen finden Sie in der Azure Repos-Referenz Service Hooks-Ereignisse.