Ausdrücke für Source Control Management Systeme

Best Practices für Git & Co: Ein Leitfaden für Commit Messages in SCM-Systemen

Marco Schulz

© Shutterstock / Photon photo

Source Control Management Systems (SCM) gehören für jeden Softwareentwickler zum Standard Repetitor. Aus dem breiten Angebot der verfügbaren Tools [1], hat sich Git als eine der beliebtesten Lösung heraus kristallisiert. Obwohl heutzutage viele Nutzer mit den weiterführenden Konzepten im Umgang mit SCM-Werkzeugen sehr geübt sind, wird die Möglichkeit zu jedem Commit eine Beschreibung zu hinterlegen etwas Stiefmütterlich behandelt. Das Formulieren aussagekräftiger Commit Messages kann in vielen Situationen die Produktivität im Entwicklungsteam verbessern.

Best Practices für Git & Co

Die Erkenntnis, dass Commit Messages von Bedeutung sind, haben einige Technologie-Blogs [2] [3] [4] im Internet bereits sehr anschaulich ausgeführt. Die dort beschriebenen Erfahrung haben die meisten mittlerweile ebenfalls selbst gesammelt. Viele Unternehmen haben auf diesen Umstand reagiert und formulierten Style Guides für das Verfassen von Commit Messages. Beim Durchstöbern der Repositorien des Cloud Source Code Hosters GitHub ist eine deutliche Verbesserung der gesamten Situation zu erkennen.

Trotz der vielen und sehr wertvollen Ratschläge gibt es einiges an Optimierungsmöglichkeiten. Eine wesentliche Überlegung ist die Tatsache, dass man als Entwickler seinen Fokus auf das Umsetzen der geforderten Funktionalität gerichtet hat und weniger auf die ebenso wichtige Dokumentation. Das Problem ergibt sich daraus, dass man sehr stark in die Thematik vertieft ist und viele der Details, die für Außenstehende wertvoll sind, als zu trivial bewertet. Dieser Umstand erschwert es, einen geeigneten Kommentar zu verfassen.

Es finden sich häufig kommentierte Revisionen mit der Beschreibung: Anpassen der Buildlogik. Dies gibt aber keinen Aufschluss darüber, um was für eine Anpassung es sich handelt. Wurde die Versionsnummer für ein Release verändert oder wurde eine neue  Abhängigkeit zu einer Bibliothek hinzugefügt? Oder wurde die aktuelle Version eines Artefaktes wie JUnit angepasst und musste gegebenenfalls diese Anpassung wegen Inkompatibilitäten zurückgezogen? Alle diese Informationen bieten einen enormen Mehrwert in der Projektarbeit, ohne dass E-Mail-Postfächer verstopft werden. Jeder Entwickler erkennt mit einem Blick in die Revisionshistory des SCM-Systems den aktuellen Status des Projektes.

Um diese Situation zu entlasten, hat der Autor eine Methode entwickelt, die es dem Nutzer durch ein vordefiniertes Vokabular ermöglicht, seine Arbeit leichter zu reflektieren und sein Ergebnis so ausdrucksstark formulieren zu können. Die erarbeiteten Ausdrücke orientieren sich vollständig an dem üblichen Sprachgebrauch in Softwareentwicklungsprojekten. Die hier beschrieben Methodik eignet sich übrigens auch für andere Bereiche der Softwareentwicklung. Die vorgestellten sprachlichen Mittel können ebenso in agilen Team-Besprechungen angewendet werden. Speziell in zeitlich limitierten Treffen, wie bei den Daily Scrum Meetings, kann dies die Kommunikation verbessern.

Strukturelemente

Wie bereits erwähnt, handelt es sich bei der vorgestellten Methode um eine Sprache mit einem sehr begrenzten Wortschatz. Für die Notation wurden die Standards der Softwareentwicklung berücksichtigt. Wichtigste Bezugselemente sind der Release-Prozess und das Semantic Versioning [5]. Um künftig eine maschinelle Auswertung ermöglichen zu können, ist ein Kommentar in fünf Bereiche untergliedert: FuctionID, Labels, Specification, TaskID und Comment. Diese fünf Elemente unterliegen einer festen Notation, welche in Abbildung 1 grafisch dargestellt ist.

Abbildung 1: Strukturelemente

Die erste Zeile besteht aus einem Identifier, welcher eine FunktionsID repräsentiert. An zweiter Stelle kennzeichnet ein Label den zugehörigen Kontext, welcher in der dritten Position spezifiziert wird. Die zweite Zeile mit der Referenz zur TaskID aus dem Issue Management, sowie die dritte Zeile mit einem ausführlichem Kommentar sind optional. Die Wahl einer FunktionsID, anstatt einer TaskID bzw. einer IssueID begründet sich aus verschiedenen Überlegungen. Zum einem soll die hier vorgestellte Lösung möglichst flexibel für allerlei Projekte gehalten sein. So wird man der Tatsache gerecht, dass es Projekte geben kann, die mit keinem Issue-Management-System verknüpft sind.

Ein weiterer Aspekt ist dem Umstand geschuldet, dass es vielfach vorkommt, dass Funktionalitäten über mehrere Tasks verteilt sind. Schneidet man allerdings die Anwendung nach deren Funktionen, wie es beispielsweise in dem Projekt TP-CORE auf GitHub [6] der Fall ist, können sämtliche Revisionen der entsprechenden Funktionalität zugeordnet werden. Dies erlaubt eine neue Betrachtungsweise durch Metriken. Mit einer Suche über die FunktionsID lassen sich sämtliche Revisionen innerhalb eines Releases feststellen, die Hinweise zu tatsächlichen Aufwänden geben. Durch Labels wie BUGFIX oder IMPLEMENT kann der Evolutionsprozess des gesamten Artefakts genauer eingeschätzt werden. Die darauffolgende Spezifikation fokussiert die Details. In der nachfolgenden Übersicht wird ein Basisvokabular für Labels und deren zugehörigen Spezifikation definiert.

Das Vokabular kann natürlich bei Bedarf an eigene Anforderungen weiter angepasst werden. Adaptionen sollten der Übersicht wegen sehr genau abgewogen werden und nur dann eingeführt werden, wenn mit den vorhandenen Mitteln der Prozess nicht beschrieben werden kann. Werden bestehende Strukturen erweitert, kann dies künftig den Einsatz von zusätzlicher Standardsoftware erschweren, da hier ebenfalls Anpassungen vorzunehmen sind, weil Abweichungen bestehender Konventionen vorhanden sind.

  1. #INIT – Initialisiert ein Repository oder ein neues Release
    • repro:documentation / configuration …
    • archetype:jar / war / ear / pom / zip …
    • version:version
  2. #IMPLEMENT – Implementieren einer neuen Funktion
    • function:clazz
  3. #CHANGE – Ändern einer bestehenden Funktion
    • function:clazz
  4. #EXTEND – Erweitern einer vorhandenen Funktion
    • function:clazz
    • attach:clazz
  5. #BUGFIX – Fehlerkorrektur
    • priority:critical / medium / low / design
  6. #REVIEW – Qualitätssicherung
    • refactor:function
    • analyze:quality
    • migrate:function
    • format:source
  7. #RELEASE – Fertigstellung eines Artefaktes zur Auslieferung
    • version:version
  8. #REVERT – Rücknahme einer Revision
    • commit:id
  9. #BRANCH – Erzeugen einer Verweigung
    • create:name
    • stash:branch
  10. #MERGE – Zusammenführen einer Verzweigung
    • from:branch
    • to:branch
  11. #CLOSE – Schließen eines Entwicklungszweiges.
    • branch:name

Auch wenn das vorgestellte Konzept leicht anzuwenden ist, soll an dieser Stelle ein einfaches Beispiel einer Commit Message die Zusammenhänge skizzieren.

[CORE-02] #IMPLEMENTfunction:GenericDAO

<Core_0021526>

{Generic Data Access Object Pattern for centralized database access.}

Die hier dargestellte Commit Message besagt, dass die Funktion GenericDAO, welche der FunktionsID CORE-02 zugeordnet ist, implementiert wurde. Der zugehörige JIRA Task lautet: Core_0021526.

Best Practice

Auch wenn die Länge der Commit Messages nicht limitiert sind, ist es empfehlenswert, die Zeichenlänge der ersten Zeile auf 80 bis 100 zu begrenzen. Lässt man sich beispielsweise die History in einem Client wie TortoiseGit oder SmartGit anzeigen, wird die erste Zeile in der Übersicht dargestellt. Ist die darin enthaltene Nachricht zu lang, muss sie abgeschnitten werden, und der Vorteil einer kompakten Darstellung wurde somit verschenkt (Abb. 2).

Abbildung 2: TortoiseGit History

Ein anderer Punkt ist die Thematik, dass nicht alle Aktivitäten, die Änderungen im Code Repository erfordern, einer speziellen Funktion zugeordnet werden können. Anpassungen der Buildlogik sind beispielsweise solche Tätigkeiten. Für diese Fälle können projektübergreifende FunktionsIDs angelegt werden. Beispiele sind:

  • [CM-000] INIT – Erzeugen oder initialisieren eines Repositories
  • [CM-010] REVIEW – Projektübergreifende Qualitätsanpassungen durch ein Architekturboard.
  • [CM-020] BRANCH – SCM Aktivität
  • [CM-030] MERGE – SCM Aktivität.
  • [CM-040] RELEASE – Anpassen der Buildnummer eines Artefakts für ein Release.
  • [CM-050] build management – Hinzufügen von weiteren Bibliotheken.

Das Kürzel CM steht hier für Konfigurationsmanagement. Die Tätigkeiten {INIT, REVIEW, etc.} stellen in diesem Fall die Funktionsbeschreibung dar und kein Label. Ein typisches Beispiel einer solchen administrativen Tätigkeit ist das Initialisieren des Code Repositories.

[CM-000] #INIT ’archtype:jar’
{Initial the repository for Java JAR library.}

Um ein Gefühl für die Mächtigkeit des hier vorgestellten Konzepts zu entwickeln, ist im unteren Kasten ein Beispielprojekt mit verschiedensten Revisionen aufgeführt. Diesem Beispiel liegt die auf GitHub publizierte Bibliothek TP-CORE [6] zugrunde, welche als Java Artefakt auf Maven Central deployed und released wurde.

 

Beispielprojekt

Beispiel-Revisionen eines Projektes mit vorangestellten Revisionummern:

01 [CM-000] #INIT ’archtype:jar’{Initial the repository for Java JARlibrary.}

02 [CORE-05] #IMPLEMENT ’function:AppConfigDO’

{Domain Object for application configuration.}

03 [CM-010] #REVIEW ’analyze:quality’

{Formatting, fix Checkstyle hints, JavaDoc & test coverage}

04 [CORE-05] #IMPLEMENT ’function:ConfigurationDAO’

{Add the ConfigurationDAO implementation.}

05 [CORE-05] #EXTEND ’attach:tests’

{Create test cases for Bean Validation.}

06 [CORE-05] #EXTEND ’function:AppConfigDO’

{Change Primary Key to UUID and extend tests.}

07 [CORE-05] #CHANGE ’function:AppConfigDO’

{Rename to ConfigurationDO and define table indexes.}

08 [CORE-05] #EXTEND ’attach:tests’

{Update test cases for application configuration.}

09 [CORE-05] #EXTEND ’function:ConfigurationDAO’

{Update the implementation for ConfigurationDAOImpl.}

10 [CORE-05] #EXTEND ’function:ConfigurationDO’

{Add field mandatory.}

11 [CM-010] #REVIEW ’migrate:JUnit’

{Migrate Test cases from JUnit4 to JUnit5.}

12 [CM-010] #REVIEW ’analyze:quality’

{Fix JavaDoc, Checkstyle & Findbugs.}

13 [CM-050] #EXTEND ’function:POM’

{Update SCM connection to GitHub.}

14 [CM-050] #EXTEND ’attach:APIguards’

{Attach annotation for API documentation.}

15 [CORE-05] #REVIEW ’refactor:ConfigurationDO’

{FindBugs: optimize constructor parameters.}

16 [CM-040] #RELEASE ‘version:1.0’

{Prepare Artifact for Release.}

17 [CM-020] #BRANCH ‘create:1.0’

{Create BugFix Branch for Version 1.0}

18 [CM-040] #RELEASE ‘version:1.0.1’

{Adapt Maven GAV parameter for deploy on Maven Central.}

Resümee

Wie gezeigt werden konnte, ist die Verwendung strukturierter Commit Messages sehr leicht in bestehende Prozesse einzubinden. Die daraus resultierenden Vorzüge sind vielfältig und eröffnen neue Möglichkeiten, Informationen aus Source-Control-Management-Systemen zu gewinnen. Die in diesem Artikel zugrundeliegende wissenschaftliche Ausarbeitung findet sich frei verfügbar auf ResearchGate [7] zum Download bereit. Der in englischer Sprache geschriebene Text gibt zusätzliche Anregungen, wie die Informationsgewinnung in SCM-Systemen weiter verbessert werden kann.

Verwandte Themen:

Geschrieben von
Marco Schulz
Marco Schulz
Marco Schulz studierte an der HS Merseburg Diplominformatik. Sein persönlicher Schwerpunkt liegt in der Automatisierung von Build-Prozessen und dem Softwarekonfigurationsmanagement. Seit über zehn Jahren entwickelt er auf unterschiedlichen Plattformen Webapplikationen. Derzeit arbeitet er als freier Consultant und ist Autor verschiedener Fachartikel.
Kommentare

Hinterlasse einen Kommentar

3 Kommentare auf "Best Practices für Git & Co: Ein Leitfaden für Commit Messages in SCM-Systemen"

avatar
400
  Subscribe  
Benachrichtige mich zu:
Patrick Schulz
Gast

An sich eine gute Idee.
Ich verstehe allerdings den Sinn hinter den curly braces im Kommentar überhaupt nicht.

Felix B.
Gast

Eine Struktur in die Commit Messages zu bringen halte ich für sehr sinnvoll. Für mich fehlt allerdings neben dem „Was“ noch das „Warum“. Es sollte nicht nur ersichtlich sein, was geändert wurde, sondern eben auch aus welchem speziellen Grund die Änderung nötig war.

Alex
Gast

Hmm, muss das wirklich so formalisiert sein? Es gibt schon gute und pragmatische Ideen für verständliche Commit messages, z.B. das „Standardwerk“: https://chris.beams.io/posts/git-commit/
Hält man sich daran, ist dies für andere gut und leicht verständlich, ohne dass ein neues Regelwerk gelernt werden muss. Die hier beschriebene Vorgehensweise richtet sich mE eher an Maschinen als an Menschen.