Best Practices für gute Check-ins

Versionskontrolle ist ein zentraler Bestandteil eines jeden Softwareentwicklungsprojekts. Im Zentrum steht dabei der Check-in von Code oder anderen Assets in das Repository. Gute Check-ins verbessern den Prozess der Versionskontrolle für Reviewer, Build- und Test-Techniker sowie für die Programmierer selbst.

In Pocket speichern vorlesen Druckansicht 9 Kommentare lesen
Lesezeit: 7 Min.
Von
  • Sven Erik Knop
Inhaltsverzeichnis

Versionskontrolle ist ein zentraler Bestandteil eines jeden Softwareentwicklungsprojekts. Im Zentrum steht dabei der Check-in von Code oder anderen Assets in das Repository. Gute Check-ins verbessern den Prozess der Versionskontrolle für Reviewer, Build- und Test-Techniker sowie für die Programmierer selbst.

Gute Check-ins können die Entwicklung und insbesondere den Build-Prozess des Produkts unterstützen. Das Problem besteht jedoch oft darin, dass sich Unternehmen nicht darauf einigen können, was genau ein gutes Check-in ausmacht. In der Vergangenheit etwa wurde ein Check-in schon für "gut genug" erachtet, wenn es keine Fehler beim Build-Prozess verursachte. Dabei steckt viel mehr Potenzial in einem Check-in.

Aktuelle Best Practices verstehen zum Beispiel den Inhalt eines Check-ins als nützlichen Teil des Entwicklungsprozesses. Welche Eigenschaften muss also ein gutes Check-in erfüllen? Eine Bestandsaufnahme.

Ein gutes Check-in dient einem einzigen Zweck, der in der Regel im Voraus klar definiert wird, und gehört zu einer bestimmten Aufgabe, die einem Entwickler oder einem Entwicklerteam zugewiesen wurde. Ein Beispiel hierfür wäre das Hinzufügen eines Features oder Beheben eines Bugs. Ein Check-in sollte dabei nicht als Backup fungieren.

Mehr Infos

Shelving

Einige Versionierungssysteme unterstützen das sogenannte Shelving. Es erlaubt, eine Änderung temporär im zentralen Repository zu sichern, ohne einen Commit durchzuführen. Diese Funktion ermöglicht Backups, Task Switching, Tests auf anderen Plattformen und Code Reviews.

Entsprechende Zwischenänderungen können im gemeinsamen Repository gelagert werden, ohne jedoch permanent eingecheckt zu werden. Bewerkstelligen lässt sich das etwa durch die Shelving-Funktion eines Versionierungssystems oder kurzlebige Branches.

Eine Aufgabe wird normalerweise in mehrere Unteraufgaben unterteilt, jede von ihnen mit einem klar definierten Zweck. Solche Unteraufgaben können ihre eigenen, individuellen Check-ins enthalten oder in einem sogenannten Task-Branch beziehungsweise einem dezentralisierten Repository kombiniert sein.

Werden die einzelnen Änderungen überschaubar gehalten und ist ihr Wirkungsbereich eng begrenzt, werden sie leichter nachvollziehbar und lassen sich einfacher prüfen und verifizieren.

Jedes Check-in besitzt üblicherweise eine Beschreibung, doch in Bezug auf ihren Umfang und ihre Qualität herrschen oft große Unterschiede. Bei manchen Entwicklerteams etwa bestehen strenge Vorgaben in Bezug auf die Beschreibungen; sie sind durch Vereinbarungen geregelt oder verwenden bestimmte Schlüsselwörter.

Eine gute Beschreibung erläutert den Zweck sowie den Wirkungsbereich des Check-ins. In manchen Fällen ist ein "Einrückungen korrigiert, keine Funktionsänderung" vollkommen ausreichend, um den Zweck darzustellen. In anderen Situationen kann eine ausführlichere Erklärung erforderlich sein.

Es besteht allerdings keine Notwendigkeit, jedes noch so kleine Detail einer Änderung innerhalb des Check-ins zu erwähnen, denn diese werden durch einen Blick auf die Code-Unterschiede im Versionsmanagement-System deutlich. Im Einzelfall kann zudem eine Erklärung der verwendeten Algorithmen angemessen sein, die dem Leser hilft, den vorliegenden Prozessablauf zu verstehen.

Ein widerspruchsfreies Projekt zeichnet sich dadurch aus, dass es den Build-Prozess durchlaufen kann und die entsprechenden Tests besteht. Diese Konsistenz bezieht sich auch auf das Check-in in ein Distributed Version Control System (DVCS) wie Git oder Mercurial. Der beste Ansatz, ein schlechtes Check-in zu erkennen, besteht darin, ältere Check-ins erneut zu laden und zu testen. Dabei sollte man bei einem früheren Projektstand beginnen, bei dem alles in Ordnung war, und sich dann zeitlich vorarbeiten, bis das schlechte Check-in auftritt. Es ist schwer, Fehlern durch ein früheres Check-in nachzugehen, wenn die vorherigen Änderungen nicht einmal den Build-Prozess zulassen.

Des Weiteren sollte jedes Check-in entsprechende Testfälle umfassen, welche die Änderungen im Sinne der Konsistenz verifizieren. Werden neue Features und ihre Tests gemeinsam aufbewahrt, vereinfacht das die Weitergabe einer Änderung an einen anderen Branch oder in ein anderes Repository.

Ein Check-in sollte alle Änderungen enthalten, die für die Build- und Test-Prozesse benötigt werden. Dazu gehören entsprechende Aktualisierungen der Anmerkungen und anderer zugehöriger Dokumentationen. Analog zu den gerade erwähnten Testfällen lassen sich mit einem derart umfassenden Check-in die entsprechenden Änderungen einfacher und sicherer weiter verbreiten.

Alle neuen Programmierschnittstellen, die durch ein Check-in eingeführt werden, sollten zumindest mit einem Methoden-Stub implementiert sein. Ein Beispiel: Das Check-in einer neuen oder erweiterten Klasse in einer C++-Header-Datei ohne entsprechende Implementierung besteht unter Umständen zwar die lokale Build- und Teststufe, andere Nutzer können dadurch jedoch später Build- oder vielleicht sogar Laufzeitfehler erhalten.