pre-commit

Ich war auf der Suche nach eine Lösung, um bestimmte Dateien in meinem GIT-Repository zu überprüfen. Die für mich naheliegendste Lösung war, die Pipeline um diese Überprüfung zu erweitern. Das funktioniert ohne Probleme, das unpraktische ist allerdings, dass Fehler erst in der Pipeline auftauchen. Ich kann die Tools zur Überprüfung zwar lokal ausführen, aber wenn ich ehrlich bin, dann mache ich das einfach nicht. Daher wäre eine automatische lokale Überprüfung von Vorteil, die im besten Fall auch noch einfach für Andere zugänglich ist. Die Antwort lautet pre-commit, welches auf git hooks aufbaut und vor dem Commit (also pre-commit) ausgeführt wird. Es werden auch alle anderen hooks von git unterstützt, das soll jedoch heute nicht das Thema sein.

Die Einrichtung von pre-commit ist recht einfach und ich werde dies hier erläutern. Zu nächste benötigt ihr Python und dessen Paketmanagementsystem pip, da pre-commit in Python geschrieben wurde.

Unter Linux (Debian/Ubuntu) geht das wie folgt. Auf anderen Systemen findet ihr hier die Installationsanleitungen.

sudo apt update
sudo apt install python3 python3-pip python3-venv -y

Jetzt könnt ihr pre-commit in der aktuellen Version installieren. Unter Debian müsst ihr hierzu eine virtuelle Umgebung einrichten, die ihr dann immer mit source ~/.venv/bin/activate aktivieren müsst, bevor ihr pre-commit verwenden könnt. Das ist notwendig, da ihr sonst eventuell Python-Abhängigkeiten von eurem Betriebssystem und anderen Applikationen durcheinander bringen könnt.

cd ~
python -m venv .venv
source ~/venv/bin/activate
pip install pre-commit

Wenn euch die aktuellste Version nicht so wichtig ist, kommt unter Debian auch pre-commit als Paket mit sudo apt install pre-commit -y. Dann müsst ihr auch nicht die virtuelle Umgebung einrichten und habt das Tool immer direkt zur Verfügung.

Ihr könnt jetzt erst mal prüfen, ob die Installation von pre-commit funktioniert hat.

pre-commit --version

Jetzt könnt ihr pre-commit für euer Repository konfigurieren. Dazu benötigt ihr als Erstes eine .pre-commit-config.yaml-Datei im Wurzelverzeichnis eures Repository. Ihr könnt diese wie folgt initialisieren.

pre-commit sample-config > .pre-commit-config.yaml

Als Zweites müsst ihr jetzt noch pre-commit in eurem Repository aktivieren/installieren. Das ist immer notwendig, wenn ihr das Repository neu auf einen Rechner klont. Das liegt daran, dass pre-commit, sich in das .git/hooks/pre-commit einhängt und die githooks nicht Teil eures Sourcecodes sind.

pre-commit install

pre-commit ist jetzt konfiguriert. Wenn man sich die .pre-commit-config.yaml-Datei anschaut, dann sieht man, dass dort unterschiedliche hocks definiert sind. Unter anderem ein trailing-whitespace, und end-of-file-fixer. Diese hooks könnt ihr jetzt einfach mal mit dem folgenden Befehl für alle Dateien ausführen.

pre-commit run --all-files

Die Ausführung dieses Befehls ist auch die Empfehlung beim Einführen neuer hooks, da damit automatisch alle Dateien den gewünschten Regeln entsprechen. Wenn man das nicht möchte, dann ist das auch nicht notwendig, dann werden immer nur die Dateien, die teil des Commits sind, an die Regeln angepasst.

Die hooks arbeiten, wie ich finde, sehr intelligent, da ihr alle Tools einbinden könnt, sobald diese ein .pre-commit-hooks.yaml in ihrem Repository eingecheckt haben, die beschreibt, wie pre-commit das Tool ausführen muss. Dazu einfach das gewünschte Repository über repo referenzieren und die in der .pre-commit-hooks.yaml definierte id als hooks hinzufügen. Eine große Auswahl an hooks findet ihr hier.

Wenn ihr jetzt also ganz normal einen Commit macht, wird immer automatisch pre-commit ausgeführt und wenn ihr das Repository auf einen anderen Computer herunterladet, dann müsst ihr nur pre-commit install ausführen, um dort den gleichen Regeln zu folgen.

git add .
git commit -m 'Add `pre-commit` to lookslikematrix.'

Das wird zu dem folgenden Output führen, wenn alle Regeln passen.

trim trailing whitespace.................................................Passed
fix end of files.........................................................Passed
check yaml...............................................................Passed
check for added large files..............................................Passed
[feature/pre-commit d0f5f59] Write `pre-commit` blog post.
 30 files changed, 139 insertions(+), 40 deletions(-)
 create mode 100644 .pre-commit-config.yaml
 create mode 100644 _posts/2023-12-18-pre-commit.markdown
 create mode 100644 assets/pre-commit.png

Oder zu folgendem Output, wenn ein Fehler in der Datei war.

trim trailing whitespace.................................................Failed
- hook id: trailing-whitespace
- exit code: 1
- files were modified by this hook

Fixing _posts/2023-12-18-pre-commit.markdown

fix end of files.........................................................Passed
check yaml...........................................(no files to check)Skipped
check for added large files..............................................Passed

Ich finde den Ansatz von pre-commit toll, weil man einfach die Möglichkeit hat ein eigenes Tool zu entwickeln, dass dann nur über eine Datei im Repository erweitert wird, um im pre-commit Kontext zu funktionieren.

Ich hoffe, diese Anleitung hat euch geholfen. Solltet ihr noch Fragen oder Anregungen haben, dann hinterlasst gerne ein Kommentar. Ansonsten könnt ihr mir gerne einen Kaffee ☕ ausgeben.


[1]: https://pre-commit.com/

[2]: https://git-scm.com/docs/githooks

[3]: https://pre-commit.com/hooks.html