Was macht eine gute (Git/SVN) Commit-Nachricht aus?

Die so genannten “Commit-Messages” (zu deutsch etwa: “übergebende Nachrichten”) werden bei Versionsverwaltungssystemen wie z.B. SVN oder Git verwendet. Sie übermitteln mit deiner Änderung eine Nachricht, die beschreibt, welche Änderungen durchgeführt wurden. Aber was macht eine gute Commit-Message aus? Das steht in diesem Beitrag.

Was ist eine Versionsverwaltung?

Wikipedia beschreibt es eigentlich ganz schön:

“Eine Versionsverwaltung ist ein System, welches zur Erfassung von Änderungen an Dokumenten oder Dateien verwendet wird.”.

Quelle: Wikipedia/Versionsverwaltung, Stand: 13. Mai 2019

Das heißt, alle Versionen werden gespeichert und können später, falls nötig, wiederhergestellt werden. Natürlich funktioniert so eine Versionsverwaltung mit Dateien aller Art. Ich benutze es jedoch ausschließlich zum Coden, also bei Softwareprojekten. Egal ob man alleine arbeitet oder ein größeres Team hat, welches an einem Projekt arbeitet macht der Einsatz einer solchen Software noch mehr Sinn. So ist sofort sichtbar, wer wann welche Änderungen gemacht hat.

Was ist ein “Commit”?

In unserer sich stetig verändernden Welt arbeiten hundert oder sogar tausende Leute gemeinsam an einem Projekt. Linux wäre so ein Beispiel. Es entsteht unter anderem durch das Engagement von Menschen, die ihren Teil dazu beisteuern. Und nicht alle sitzen zu jeder Zeit am selben Ort oder arbeiten zur gleichen Zeit.

Auch das WordPress-Plugin-Verzeichnis hat mittels Subversion eine Versionsverwaltung spendiert bekommen. Somit können mehrere Leute an einem Plugin arbeiten ohne die Versionshistorie aus den Augen zu verlieren (auch wenn viele mittlerweile Github nutzen).

Möchte ein Programmierer eine Änderung ausführen, muss er zuerst eine lokale Kopie des Repositories (also dem “Archiv”) der Versionsverwaltung “auschecken”. In den meisten Fällen ist dies die letzte Version die hinterlegt wurde. Erst dann kann er die Änderungen lokal auf seinem Rechner durchführen. Danach lädt er sie wieder in die Versionsverwaltung hoch. Dies erstellt dann eine neue Version mit den neuen Änderungen. Diesen Vorgang nennt man “commit” (zu deutsch etwa “übergeben” oder “überstellen”).

Warum sind “Commit-Messages” notwendig?

Mit dem “Commit” sollte immer auch eine “Commit-Message”, also eine Nachricht, übergeben werden. Sie soll möglichst genau beschreiben, welche Änderungen der Entwickler durchgeführt hat. Wie oben schon erwähnt, ist es möglich, dass mehrere Benutzer gleichzeitig an etwas arbeiten. Die Kommunikation zwischen den einzelnen Programmierern ist meist sehr schwierig, da nicht immer alles sofort und persönlich abgesprochen werden kann. Das bedeutet wiederum, dass die so genannten “Commit Messages” eine Art Kommunikationsmittel sind.

Das Ziel einer “Commit Message” ist also die Änderung einer Datei oder einer Aufgabe möglichst genau und in wenigen Sätzen für andere Programmierer zu beschreiben. Damit umgeht man letztlich die einzelne und direkte Kommunikation (z.B. via Chat) zwischen Entwicklern. Daraus ergibt sich, dass sich Code-Reviews beschleunigen und Änderungen sichtbar werden, die sich so nicht aus dem Code ergeben würden.

Wer liest diese Nachrichten?

Dies ist ein wichtiger Punkt, denn es ist nicht notwendig, alle Änderungen bis ins letzte Detail zu beschreiben, wenn man weiß, wer die Zielgruppe dieser Nachrichten ist.

  • Zum einen sind dies die Leute (Programmierer) die selbst am Code arbeiten (debuggen)
  • Und die Leute, die die Timeline lesen.

Wie ist eine ideale “Commit-Nachricht” aufgebaut?

Zusammengefasst lässt sich folgendes sagen:

[Aufgabe/Projekt:] Was wurde verändert und warum? Möglichst in einer Zeile.
Leerzeile
Dos:
- Beschreiben, was da Problem verursacht hat.
- Lösungsweg (falls nicht offensichtlich).
Don'ts:
- Keine weiterführende Links (außer auf Trac-Tickets)
- Keine Codeblöcke.

Es gibt mehrere Fälle, die ich hier beschreiben möchte. Die englische Version, die jemand einmal sehr gut zusammen gefasst hat, findet man hier.

1. Eine gute Commit-Nachricht sollte eine Betreffzeile haben.

Notwendig ist nur ein kurzer Satz der beschreibt, was verändert wurde und – falls möglich – warum.

Ein möglicher Satz für eine Betreffzeile wäre zum Beispiel:

Link auf m.wordpress.com wurde repariert.

Wobei sofort klar ist, dass eine URL ausgetauscht wurde, weil sie nicht mehr funktioniert hat. Man muss also nicht schreiben: “Link auf m.wordpress.com wurde repariert, weil er nicht mehr funktioniert hat.”

Beispiel 2:

Lösche den Cache von jedem Beitrag um Speicher zu sparen.

Hier wäre eine weitere Beschreibung nicht schlecht. Denn ist nicht genau klar, warum die Caches gelöscht werden müssen. Für den Programmierer wäre es nötig in den Code zu sehen um die Änderung zu begreifen.

2. Eine Leerzeile zwischen Betreff und weiterem Text einfügen.

Als “Commit-Message” kann letztlich keine einzelne Betreffzeile haben (wie sie z.B. von E-Mail-Programmen genutzt wird). Wir machen uns diese also selbst: Die erste Zeile ist eine Betreffzeile, dann kommt eine Leerzeile und erst danach kommt ein weiterführender Text (falls nötig). Hier ein Beispiel:

Lösche den Cache von jedem Beitrag um Speicher zu sparen.

Lorem ipsum dolor sit amet, consetetur sadipscing elitr,
sed diam nonumy eirmod tempor invidunt ut labore et dolore
magna aliquyam erat, sed diam voluptua. At vero eos et accusam
et justo duo dolores et ea rebum. Stet clita kasd gubergren, no
sea takimata sanctus est Lorem ipsum dolor sit amet.

Die Leerzeile sorgt optisch für eine Trennung. Dadurch ist das Lesen um einiges einfacher.

Was soll eine gute Commit-Nachricht beinhalten?

1. Sie zeigt das “Warum” auf.

Zum einen, weil die Leser der Timeline durch das Betrachten des Codes und der Commit-Nachricht lernen können, wie etwas umgesetzt wurde. Die Programmierer hingegen erhalten Einblick in die Denkweise des Programmierers der die Änderung vollzogen hat. Das wiederum macht es später leichter Fehler zu finden, die sich in der Kette “weiter oben” befinden.

Das “Warum” zu beschreiben ist manchmal sehr kniffelig. Nahe liegt zum Beispiel, dass man etwas repariert “weil es eben kaputt ist”.

Deshalb sollte man sich die fünf Warum-Fragen stellen um geistig eine ebene Tiefer nach zu haken. Beispiel:

Die Klasse in eine Hierarchie eingeteilt um es später leichter in das XY Plugin zu integrieren.

Die alte Version benötigte immer sehr viele Zeilen
an Code und einige Hacks um die Kompatibilität
herzustellen. Mit der neuen Hierarchie können wir
sehr viele Zeilen an Code und fast alle Hacks ausschließen.

Beispiel 2:

Die Möglichkeit des Filterns nach Tickets wurde entfernt

Es war nicht sehr hilfreich da es nur sehr langsam generiert wurde.
Der normale Workflow ist, dass der User direkt zur Ticket-Seite
geht und dort die Kommentare direkt einsehen kann.

Im zweiten Beispiel wird die Änderung eines Workflows dokumentiert. Jeder versteht sofort, dass dies letztlich der Grund für den Commit war.

2. Sie beschreibt, was das Problem verursacht hat.

Die meisten Änderungen bessern irgendwelche Fehler aus. Es ist also erforderlich zu beschreiben, wie der Fehler zustande kam. Also was genau den Fehler verursacht hat. Das Verständnis um die Ursache des Problems kann später anderen Programmierern helfen, ähnliche Probleme zu lösen.

Im englischen wird für das Lösen für Problemen oft das Wort “Fix” benutzt. Das sollte allerdings – falls möglich – nicht verwendet werden. Denn meistens gibt es ein besseres Tätigkeitswort dafür. Beispiel:

Setze den richtigen Dropdown-Wert, wenn das Signup-Formular von test.xyz.com aufgerufen wird.

Der Code der eigentlich dafür zuständig ist, den Dropdown-Wert
zu setzen arbeitete nicht genau. Stattdessen setzt er den Wert
auf test.xyz und die Domainendung auf .com, weil .com in der
Liste noch vor der Domain .xyz.com kam.
Die Lösung erforderte eine Neusortierung nach Domainlänge.

Im Beispiel wird also beschrieben, das der Wert des Dropdown-Menüs nicht neu gesetzt wurde, sondern dass der Code zum Setzen des Wertes neu erstellt wurde. Es wird auch beschrieben, welcher Code genau ersetzt wurde. Zum leichteren Verständnis rundet das Beispiel die Commit-Message zusätzlich ab. Am Ende wurde dann noch das “Wie”, also die Lösung präsentiert.

Englisches Beispiel:

Fix stats link on m.wordpress.com

We need double quotes, when we want to use variables in the string.
The problem was introduced in the mass sanitization of [46532].

Hier wurde kein besseres Wort für “Fix” gefunden werden, was durchaus in Ordnung ist. Darüber hinaus wurde die Nummer des Changesets angegeben, der das Problem verursacht hat.

3. Sie beschreibt die Lösung bzw. den Lösungsweg. Aber nur, wenn er nicht offensichtlich ist.

Fast immer ist das “Wie” sehr offensichtlich. Wenn man glaubt, das es das nicht ist, sollte man den Lösungsweg genauer beschreiben um den Leser beim Verstehen des Codes zu unterstützen.

Beispiel:

Ein neuer Statistik-Wert für die Bandbreite wurde hinzugefügt

Die Bandbreite wird aus den monatlichen Resultaten hochgerechnet.
Aus der Berechnung erhalten wir so für jeden Blog die
durchschnittliche Anzahl an Bytes pro Pageview. Diese Daten
werden dann in der Datei means.json zwischengespeichert. Der
gesamte Code der zur Erstellung der means.json nötig ist, befindet
sich in statischen Methoden der Klasse.

Im Beispiel wird also schon fast ein Teil des Algorithmus beschrieben. Natürlich wäre es auch möglich gewesen, dies aus dem Code heraus zu lesen. Da der Algorithmus jedoch oft sehr komplex ist, wäre sehr viel Energie dazu nötig gewesen. Die Erwähnung sagt darüber hinaus aus, dass das Wissen um den neuen Code für die weitere Entwicklung nötig ist.

4. Sie ist nicht vom Code abhängig

Das bedeutet, dass das Betrachten des Codes nicht notwendig ist, wenn man die Commit-Nachricht liest. Das wiederum bedeutet nicht, dass man jede einzelne Zeile beschreiben muss. Stattdessen sollte man den nicht-trivialen Teil genauer beschreiben.

Im Gegenteil dazu sollte man nicht direkt im Code alle Einzelheiten der Commit-Message einfügen. Die Beschreibung einer Funktion, was diese macht und welche Algorithmen sie benutzt reicht oft aus um sie zu verstehen.

Weitere interessante Vorgehensweisen

Natürlich obliegt es jedem selbst, wie er seine “Commit-Messages” schreibt. Auch kann man in seinen Teams unterschiedliche Lösungsansätze für die passende Zusammenarbeit haben. Folgendes sind daher nur weiter hilfreiche Tipps zur Gestaltung von Commit-Nachrichten.

1. Präfixe nutzen

Wenn man im Team kleine Projekte in einzelne Aufgaben unterteilt hat und diese Aufgaben einen Namen haben, macht es Sinn, diese als Präfix zu benutzen. Beispiel:

Aufgabe 309: Link auf m.wordpress.com wurde repariert.

2. Halte jeden Commit so klein wie möglich

Das bedeutet, dass man z.B. keine Verbindungswörter, wie “und” in der Betreffzeile der Commit-Nachricht verwenden sollte. Wenn man merkt, dass man mehrere Probleme oder Aufgaben in einem Commit beschreibt, sollte man sie lieber auf mehrere, einzelne Commits aufteilen.

Das ist gerade auch wichtig, wenn es sich nur um Leerzeilen-Änderungen handelt. Also wenn z.B. neue Einrückungen gemacht wurden oder ähnliches.

Links erfüllen immer “nur” den Zweck, weitere, tiefer gehende Infos zu enthalten. Die Commit-Nachricht sollte aber immer alle wichtigen Details beschreiben. Es soll nicht erforderlich sein, den Inhalt des Links zu lesen um die Änderungen zu verstehen.

4. Nicht so naheliegende Tipps

  • Viele Entwickler brauchen mehr Zeit für das Schreiben von Commit-Nachrichen als für die eigentliche Programmieraufgabe. Und das ist okay so, denn am Ende hilft es jeden anderen Programmierer die Änderung effizienter und schneller zu verstehen.
  • Gleiches gilt für die Länge des Commits: Es ist okay, wenn die Commit-Nachricht länger ist als die Änderung selbst.
  • Wenn man ein Projektmanagement-System (wie z.B. Trac) benutzt, sollte man immer auch zu den Trac-Tickets verlinken.
  • Die Vernunft und der gesunde Menschenverstand kann alle obigen Regeln jederzeit aushebeln. Wenn man glaubt eine Commit-Message sollte anders aussehen wie oben empfohlen, kann man das natürlich jederzeit machen. Die Hauptsache ist, dass alle nachfolgenden Entwickler die jeweilige Änderung richtig, prägnant und schnell verstehen können.

Neuere Leitfäden beschreiben darüber hinaus, dass man lieber das Imperativ verwenden soll um zu beschreiben, welche Auswirkung eine Änderung hat und nicht, was vorher war.

Ein Kommentar zu “Was macht eine gute (Git/SVN) Commit-Nachricht aus?