Zusammenarbeit in Git

Git-Flow, GitHub-Flow oder Trunk-Based: welches Branching-Modell zu eurem Release-Takt passt

Die Modelle unterscheiden sich weniger im Diagramm als in dem, was sie voraussetzen. Wer sie ohne diese Voraussetzungen übernimmt, bekommt lange Branches und Konflikte, die niemand mehr auflösen will.

KI-generiertDieses Bild wurde mit KI erzeugt · Yves Hoppe / KI / cmt
Seit 1997 am Markt Kleine Gruppen Präsenz und Live-Online Zertifizierte Trainer
Worum es geht

Das Modell wird nach dem Diagramm ausgewählt und nicht nach dem Auslieferungstakt

Der übliche Weg zu einem Branching-Modell führt über eine Bildersuche. Jemand findet das bekannte Diagramm mit den fünf farbigen Spuren, es sieht ordentlich aus, und ab dann heißt der Hauptbranch main, daneben liegt develop, und für jede Freigabe entsteht ein Release-Branch. Was in dem Diagramm nicht steht, ist die Voraussetzung dahinter: Es wurde für Software geschrieben, die in Versionen erscheint, die man herunterlädt und installiert, und die parallel in mehreren Ständen im Feld ist.

Übernimmt ein Team mit täglicher Auslieferung dieses Modell, entsteht ein zweiter langlebiger Branch ohne Zweck. Jede Änderung wandert zweimal, jeder Hotfix muss in beide Linien, und weil das Zurückführen regelmäßig vergessen wird, driften develop und main auseinander. Am Ende gibt es Release-Branches, die niemand mehr schließt, und Merges, bei denen niemand sicher sagen kann, welcher Stand jetzt im Betrieb läuft.

In die andere Richtung tut der Fehler genauso weh. Ein Team stellt auf einen einzigen Hauptbranch mit kurzlebigen Branches um, hat aber weder ausreichende Tests in der Pipeline noch eine Möglichkeit, halbfertige Funktionen abzuschalten. Dann steht unfertige Arbeit im Hauptstand, die Auslieferung wird blockiert, bis die letzte Funktion fertig ist, und nach drei Wochen laufen wieder wochenlange Branches, nur ohne die Struktur, die ihnen vorher Halt gegeben hat.

KI-generiertDieses Bild wurde mit KI erzeugt · Yves Hoppe / KI / cmt
Der direkte Vergleich

Drei Modelle an dem gemessen, was sie im Alltag verlangen

Verglichen werden die drei Muster, die in deutschen Entwicklungsteams tatsächlich anzutreffen sind. Interessant ist dabei weniger, wie die Branches heißen, als die Voraussetzung, ohne die das jeweilige Modell in kurzer Zeit auseinanderfällt.

Git-Flow

dauerhafte Branches für Entwicklung und Freigabe, dazu Feature-, Release- und Hotfix-Branches mit fester Reihenfolge

GitHub-Flow

ein Hauptbranch, davon kurzlebige Branches je Beitrag, Übernahme nach Review und Prüflauf

Trunk-Based

alle arbeiten auf dem Hauptstand, Branches leben Stunden bis höchstens einen Tag, Unfertiges liegt hinter Schaltern

Wie gut passt das Modell zu täglicher oder mehrfach täglicher Auslieferung?

Git-Flow

Zwischen Beitrag und Betrieb liegen zwei Merges und ein Release-Branch. Bei täglicher Auslieferung ist diese Zeremonie reiner Aufwand, und der Autor des Modells hat seinem Beitrag selbst einen Hinweis vorangestellt, dass es für Software mit fortlaufender Auslieferung nicht gedacht ist.

GitHub-Flow

Der Hauptstand ist der auslieferbare Stand. Ein übernommener Beitrag kann unmittelbar danach in den Betrieb, ohne dass eine weitere Linie bedient werden muss.

Trunk-Based

Das Modell ist genau dafür gebaut. Änderungen erreichen den Hauptstand mehrmals täglich, und die Auslieferung ist eine Entscheidung über einen Schalter und nicht über einen Branch.

Was passiert, wenn ihr mehrere Versionen gleichzeitig pflegen müsst?

Git-Flow

Dafür wurde es entworfen. Release- und Hotfix-Branches sind der vorgesehene Ort für Korrekturen an einem Stand, der beim Kunden läuft, und die Regeln für das Zurückführen sind Teil des Modells.

GitHub-Flow

Das Modell kennt nur den aktuellen Stand. Eine Korrektur an einer älteren Version müsst ihr an ihm vorbei organisieren, und dann seid ihr bei einem Wartungszweig, den das Modell nicht beschreibt.

Trunk-Based

Vorgesehen ist ein Branch, der erst bei Bedarf vom Hauptstand abgeht und auf den Korrekturen aus dem Hauptstand übertragen werden. Das funktioniert, verlangt aber Disziplin, weil die Richtung immer vom Hauptstand nach unten läuft und nie umgekehrt.

Wie groß werden die Konflikte beim Zusammenführen?

Git-Flow

Lange lebende Branches und mehrere Integrationsstufen erzeugen die größten Auflösungen, und sie fallen typischerweise kurz vor einem Termin an. Dazu kommen die Konflikte, die beim Zurückführen eines Hotfixes in die Entwicklungslinie entstehen.

GitHub-Flow

Die Branches leben Tage statt Wochen, das hält Konflikte klein. Ob es dabei bleibt, hängt daran, wie oft ihr den Hauptstand in laufende Beiträge holt.

Trunk-Based

Bei einer Lebensdauer von Stunden kann kaum etwas auseinanderlaufen. Der Preis ist, dass Aufgaben so geschnitten werden müssen, dass sie in dieser Zeit fertig werden.

Was verlangt das Modell an Automatisierung und Testabdeckung?

Git-Flow

Am wenigsten. Der Freigabezweig ist ausdrücklich der Ort für manuelle Prüfung und Stabilisierung, und genau deshalb ist das Modell für Teams ohne belastbare Pipeline noch immer eine ehrliche Antwort.

GitHub-Flow

Der Prüflauf vor der Übernahme muss so viel abdecken, dass ein Review plus grüne Pipeline für die Freigabe reichen. Das ist machbar, ohne dass alles automatisiert sein muss.

Trunk-Based

Am meisten. Ohne schnelle, verlässliche Tests im Hauptstand ist ein defekter Stand nicht die Ausnahme, sondern der Normalfall, und dann steht das ganze Team. Die Rückmeldezeit der Pipeline ist hier eine harte Voraussetzung und keine Kennzahl.

Wie schnell versteht jemand Neues, wo er abzweigt und wohin er zurückführt?

Git-Flow

Fünf Branch-Arten mit festgelegten Quellen und Zielen. Ohne Spickzettel oder ein Hilfswerkzeug macht jeder mindestens einmal den Fehler, einen Hotfix nur in eine der beiden Linien zu bringen.

GitHub-Flow

Vom Hauptstand abzweigen, Beitrag stellen, zurückführen. Das ist in zwei Sätzen erklärt und deckt sich mit dem, was die Oberflächen von sich aus anbieten.

Trunk-Based

Der Ablauf ist noch einfacher, die Regeln drumherum sind es nicht. Wann etwas hinter einen Schalter gehört, wann der Schalter wieder verschwindet und wie ihr mit einem defekten Hauptstand umgeht, muss vereinbart und eingeübt sein.

Wie gut lässt sich nachweisen, welcher Stand beim Kunden läuft?

Git-Flow

Jede Freigabe hat einen eigenen Branch und einen Versionsstand, das ist für eine Abnahme oder einen Nachweis gegenüber einer Prüfstelle die bequemste Ausgangslage.

GitHub-Flow

Über Tags und die Aufzeichnung der Auslieferung ist es lückenlos möglich, das Modell selbst gibt aber nichts vor. Wer nichts einrichtet, hat später nur die Pipeline-Protokolle.

Trunk-Based

Dasselbe gilt hier, mit einer zusätzlichen Frage: Weil eine Funktion über einen Schalter aktiv wird, gehört zum Nachweis nicht nur der Commit, sondern auch der Zustand der Schalter zum Zeitpunkt der Auslieferung.

Was passt wann

Wenn ihr eine Anwendung im Web betreibt, überall derselbe Stand läuft und ihr wöchentlich oder öfter ausliefert
nehmt GitHub-Flow und steckt die Mühe in die Prüfläufe vor der Übernahme.
Wenn ihr Software ausliefert, die beim Kunden installiert wird, und mehrere Stände mit Korrekturen versorgt
bleibt bei den Release- und Wartungszweigen aus Git-Flow, aber verzichtet auf den zweiten dauerhaften Entwicklungszweig, wenn er euch nichts bringt.
Wenn eure Pipeline in wenigen Minuten verlässlich Rückmeldung gibt und ihr Funktionen abschalten könnt
geht auf Trunk-Based und messt vorher, wie lange eure Branches heute leben, um den Fortschritt zu sehen.

Fünf Fragen führen zum passenden Modell

  1. 01 Wie oft liefert ihr tatsächlich aus, täglich oder zu festen Terminen?
  2. 02 Wie viele Versionen müsst ihr gleichzeitig mit Korrekturen versorgen?
  3. 03 Wie alt ist ein Branch bei euch im Schnitt, wenn er zusammengeführt wird?
  4. 04 Könnt ihr eine halbfertige Funktion im Hauptstand abschalten?
  5. 05 Wie viel prüft die Pipeline, bevor jemand auf den Übernehmen-Knopf drückt?
Was du mitnimmst

Was ihr klären müsst, bevor ihr euch für ein Modell entscheidet

Die Wahl fällt an sechs Punkten, und fünf davon haben nichts mit Git zu tun. Wer sie beantwortet hat, kann das passende Modell in wenigen Minuten benennen, und die Diskussion über Diagramme erübrigt sich.

Den tatsächlichen Auslieferungstakt aufschreiben

Nicht den gewünschten, sondern den, den ihr in den letzten sechs Monaten wirklich hattet. Täglich, wöchentlich, quartalsweise oder nach Absprache mit dem Kunden: Diese eine Angabe schließt bereits die Hälfte der Modelle aus.

Zählen, wie viele Stände ihr gleichzeitig unterstützt

Läuft überall dasselbe, weil ihr eine Anwendung im Web betreibt, braucht ihr keine Release-Branches. Habt ihr Kunden auf drei Ständen, für die es noch Korrekturen gibt, braucht ihr für jeden dieser Stände eine dauerhafte Linie, und das gibt euch kein Modell geschenkt.

Die Lebensdauer eines Branches messen

Schau nach, wie alt eure offenen Branches im Schnitt sind. Alles jenseits weniger Tage erzeugt Konflikte, die überproportional mit der Zeit wachsen. Wenn diese Zahl hoch ist, ist der Zuschnitt der Aufgaben das Problem und nicht das Modell.

Klären, wie eine halbfertige Funktion im Hauptstand liegen kann

Ohne eine Antwort darauf ist Trunk-Based nicht möglich. Die Antwort heißt Feature-Flag im Code, eine neue Umsetzung neben der alten hinter derselben Schnittstelle, oder eine Funktion, die noch nicht von der Oberfläche aus erreichbar ist. Der Schalter ist dabei kein Dauerzustand, er gehört wieder entfernt.

Prüfen, was die Pipeline vor dem Zusammenführen wirklich abfängt

Ein kurzlebiger Branch funktioniert nur, wenn die automatische Prüfung so viel Vertrauen erzeugt, dass eine Übernahme keine Zeremonie braucht. Steht da nur ein Compilerlauf, ist ein zusätzlicher Integrationszweig kein Ballast, sondern das Netz, das ihr sonst nicht habt.

Freigaben von Branches trennen

Eine Freigabe braucht keinen Branch, sie braucht einen Namen. Ein Tag auf dem Commit, der ausgeliefert wurde, reicht für die Nachvollziehbarkeit. Ein Branch wird erst dann nötig, wenn auf diesem alten Stand noch weitergearbeitet werden muss, und erst in diesem Moment legt ihr ihn an.

Die Regeln in der Plattform hinterlegen

Schutz des Hauptbranches, Pflicht zum Review, erforderliche Prüfläufe, automatisches Löschen des Quellbranches nach dem Übernehmen und eine Namenskonvention für Branches. Was nicht in den Einstellungen steht, gilt nach vier Wochen nicht mehr.

KI-generiertDieses Bild wurde mit KI erzeugt · Yves Hoppe / KI / cmt

Git-Flow: wofür es einmal gebaut wurde

Das Modell stammt aus einer Zeit und aus einem Umfeld, in dem Software in Versionen erschien. Der Kunde installierte 3.2, bekam später 3.2.1 als Korrektur, und parallel entstand 3.3. Für genau diese Situation ist die Aufteilung sinnvoll: Ein Release-Branch friert den Umfang ein, während die Entwicklung weiterläuft, und ein Hotfix-Branch erlaubt eine Korrektur an einem Stand, der längst ausgeliefert ist.

Der Autor hat seinem ursprünglichen Beitrag später einen Hinweis vorangestellt, in dem er genau diese Einschränkung benennt: Für Software, die fortlaufend ausgeliefert wird, ist das Modell zu schwer, und dort ist ein einfacheres Vorgehen die bessere Wahl. Diesen Hinweis kennen erstaunlich wenige Teams, die das Modell benutzen, weil das Diagramm auf viel mehr Seiten steht als der Text daneben.

Wenn ihr in dieser Welt arbeitet, also im Anlagenbau, in der Medizintechnik, bei Software für den Kunden vor Ort oder überall dort, wo eine Version abgenommen wird, ist Git-Flow keine schlechte Wahl. Nur ein Teil davon lohnt eine Prüfung: der zweite dauerhafte Entwicklungszweig. Er ist der teuerste Bestandteil, und viele Teams kommen mit Freigabezweigen direkt vom Hauptstand genauso weit.

Trunk-Based: was es voraussetzt, bevor es etwas bringt

Die Beschreibung klingt einfach: Alle arbeiten am Hauptstand, Branches leben Stunden. Die Voraussetzungen dafür sind es nicht. Erstens braucht ihr einen Weg, unfertige Arbeit auszuliefern, ohne sie sichtbar zu machen. Das ist im einfachsten Fall eine Bedingung im Code, die eine Funktion erst freigibt, wenn ein Schalter gesetzt ist, und im aufwendigeren Fall eine zweite Umsetzung hinter derselben Schnittstelle, zwischen denen umgeschaltet wird.

Zweitens braucht ihr Aufgaben, die in dieser Zeit fertig werden. Das ist die eigentliche Umstellung, und sie betrifft nicht Git, sondern den Schnitt der Arbeit: Eine Änderung an der Datenbank wird in mehrere Schritte zerlegt, die einzeln lauffähig sind, eine neue Oberfläche entsteht Stück für Stück hinter einem Schalter. Teams, die daran scheitern, scheitern nicht am Modell.

Drittens braucht ihr eine Pipeline, die in Minuten antwortet, und eine Vereinbarung für den Fall, dass der Hauptstand nicht baut. Die übliche Regel lautet: Wiederherstellen hat Vorrang vor allem anderen, und wenn die Ursache nicht in kurzer Zeit gefunden ist, wird der verursachende Commit zurückgenommen statt repariert. Ohne diese Regel steht bei jedem Fehler das ganze Team, und genau daraus entsteht dann der Ruf, Trunk-Based funktioniere nicht.

Feature-Flags sind Schulden, wenn sie bleiben

Ein Schalter, der eine unfertige Funktion verdeckt, ist ein Werkzeug mit Verfallsdatum. Solange er lebt, existieren zwei Wege durch den Code, und beide müssen getestet werden. Bei zwei Schaltern sind es vier Kombinationen, bei fünf schon zweiunddreißig, und niemand testet die alle. Deshalb gehört zu jedem Schalter von Anfang an die Angabe, wann er wieder verschwindet, und die Entfernung gehört als Aufgabe ins Backlog und nicht in die Erinnerung eines Einzelnen.

Es lohnt sich, zwischen den Arten zu unterscheiden. Ein Schalter, der eine Funktion während der Entwicklung verdeckt, lebt Tage bis Wochen und wird danach entfernt. Ein Schalter, mit dem der Betrieb eine Funktion im Störungsfall abschalten kann, lebt dauerhaft und ist eine bewusste Betriebsfunktion. Ein Schalter, der Kunden unterschiedlich behandelt, ist eigentlich Konfiguration und gehört nicht in dieselbe Schublade.

Der praktische Rat dazu ist unspektakulär: Führt eine Liste, in der jeder Schalter mit Zweck, Verantwortlichem und geplantem Entfernungsdatum steht, und schaut sie einmal im Monat durch. Das ist der Unterschied zwischen einem Werkzeug und einer Codebasis, in der nach zwei Jahren niemand mehr weiß, welcher Pfad tatsächlich läuft.

Die Regeln, die ihr unabhängig vom Modell braucht

Vier Festlegungen wirken in jedem der drei Modelle. Erstens der Schutz des Hauptbranches: kein direkter Push, kein erzwungener Push, Übernahme nur über einen Beitrag mit Review und grünem Prüflauf. Zweitens eine Namenskonvention für Branches, die die Vorgangsnummer enthält, damit sich ein Branch nach zwei Wochen noch zuordnen lässt. Drittens das automatische Löschen des Quellbranches nach der Übernahme. Viertens ein Tag auf jedem Stand, der tatsächlich ausgeliefert wurde.

Dazu kommt eine Kennzahl, die mehr über eure Zusammenarbeit sagt als das Modell: die Zeit zwischen dem ersten Commit auf einem Branch und seiner Übernahme. Wenn dieser Wert bei euch in Wochen gemessen wird, ändert kein Modellwechsel etwas, weil die Ursache im Zuschnitt der Aufgaben oder in der Wartezeit auf Reviews liegt. Wenn er in Tagen gemessen wird, habt ihr die Wahl.

Bewährt hat sich außerdem, das Zusammenführen in eine Richtung festzulegen und diese Richtung nicht zu brechen. Änderungen wandern vom Hauptstand in die Branches und von einem Beitrags-Branch in den Hauptstand, nie kreuz und quer zwischen zwei Beitrags-Branches. Sobald zwei laufende Beiträge voneinander abhängen, ist das ein Hinweis, dass die Aufgaben falsch geschnitten wurden, und dieser Hinweis ist mehr wert als jeder Merge.

Umstellen, ohne dass die Auslieferung stehenbleibt

Eine Umstellung an einem Stichtag funktioniert selten. Was funktioniert, ist eine Reihenfolge in vier Schritten. Zuerst wird gemessen, wie lange Branches leben und wie lange die Pipeline braucht; ohne diese beiden Zahlen fehlt später der Vergleich. Dann werden die Aufgaben kleiner geschnitten, bis ein Beitrag üblicherweise in ein bis zwei Tagen fertig ist. Erst danach werden Branches entfernt, und zwar der überflüssige dauerhafte Branch zuerst.

Der vierte Schritt ist der unbequeme: die Testabdeckung an den Stellen, die euch bisher der Freigabezweig abgenommen hat. Wenn dort bislang von Hand geprüft wurde, muss diese Prüfung entweder automatisiert oder bewusst an eine andere Stelle verlegt werden, etwa in eine Staging-Umgebung, in die der Hauptstand ständig ausgerollt wird. Wer diesen Schritt überspringt, verliert genau die Sicherheit, die das alte Modell trotz seiner Umständlichkeit geliefert hat.

Legt für die Umstellung außerdem ein Ende fest, an dem ihr die Zahlen von Anfang und Ende vergleicht. Wenn die Branches nach drei Monaten immer noch drei Wochen leben, war das Modell nicht das Problem, und die Diskussion gehört dann zurück in die Planung und nicht in die Werkzeugeinstellungen.

Dazu passende Kurse

Wenn ihr das Modell nicht nur beschließen, sondern auch in den Einstellungen der Plattform verankern wollt, sind Git-Kurse mit Blick auf Branches, Freigaben und Pipelines die kürzeste Abkürzung.

Weil kurzlebige Branches ohne verlässliche Prüfläufe nicht funktionieren, gehören die DevOps-Kurse rund um Auslieferung und Automatisierung zur selben Entscheidung.

Wissen prüfen

Wie sicher bist du beim Thema wirklich?

Lesen fühlt sich schnell nach Können an. Ein kurzer Test zeigt dir, was davon schon sitzt und wo sich ein Kurs lohnt. Kostenlos, ohne Anmeldung, mit einer Erklärung zu jeder Antwort.

Sehr umfangreicher Überblick über Zusammenhänge und Anwendungsbereiche. Sehr zu empfehlen.
Einführung in die Programmierung für Programmiereinsteiger
Effektives, gemeinsames Erarbeiten der Aufgaben mit vielen praktischen Tipps.
Groovy Grundkurs
Sehr guter Trainer und gute Aufbereitung der Inhalte und auch eingehen auf Fragen der Beteiligten.
Unreal Engine Kurs für Einsteiger

Häufige Fragen

Ist Git-Flow überholt?
Nein, aber es ist kein Standardvorgehen. Wenn ihr Software ausliefert, die beim Kunden installiert wird, und mehrere Stände gleichzeitig mit Korrekturen versorgen müsst, ist es weiterhin eine tragfähige Antwort. Für eine Anwendung im Web mit einem einzigen laufenden Stand ist es zu schwer, und darauf weist der Autor des Modells selbst hin.
Brauchen wir wirklich einen zweiten dauerhaften Branch neben main?
Nur, wenn zwischen dem Fertigstellen einer Änderung und ihrer Auslieferung regelmäßig eine längere Phase liegt, in der weiterentwickelt wird. Fällt beides zeitlich zusammen, ist der zweite Branch ein zusätzlicher Merge ohne Nutzen. Ein Release-Branch, der bei Bedarf vom Hauptstand abgeht, deckt denselben Zweck ab und lebt nur so lange, wie er gebraucht wird.
Wie lang darf ein Branch leben?
Als Faustregel: so lange, dass der Merge am Ende noch von einer Person in einem Zug verstanden werden kann. In der Praxis sind das ein bis drei Tage. Wichtiger als die Zahl ist die Richtung: Wenn eure Branches über Monate hinweg immer älter werden, liegt die Ursache fast nie in Git, sondern im Zuschnitt der Aufgaben oder in der Wartezeit auf Reviews.
Wie liefern wir aus, wenn eine Funktion noch nicht fertig ist?
Über einen Schalter im Code, der die Funktion erst freigibt, wenn er gesetzt ist, über eine zweite Umsetzung hinter derselben Schnittstelle, zwischen denen umgeschaltet wird, oder indem die Funktion vorerst nicht von der Oberfläche aus erreichbar ist. Zu jedem dieser Schalter gehört von Anfang an ein Termin, an dem er wieder verschwindet, sonst sammelt ihr Pfade an, die niemand mehr testet.
Was tun wir, wenn der Hauptstand kaputt ist?
Vereinbart vorher, dass die Wiederherstellung Vorrang vor allem anderen hat, und dass nach einer kurzen Frist der verursachende Commit zurückgenommen wird, statt weiter nach der Ursache zu suchen. Ein zurückgenommener Beitrag lässt sich in Ruhe reparieren und erneut stellen; ein Hauptstand, der einen halben Tag nicht baut, blockiert alle.

Passt thematisch dazu

Sobald mehrere Stände gleichzeitig im Feld stehen, hängt das Modell an einer festen Zuständigkeit, und in größeren Häusern trägt sie die Rolle, die Bau, Freigabe und Rücknahme verantwortet .

Persönlich für dich da

Deine Ansprechpartner

Du bist dir nicht sicher, welcher Kurs oder welches Level zu dir passt? Wir beraten dich persönlich und kostenlos.

Yves Hoppe

Yves Hoppe

Weiterbildung & Beratung

Hilft dir, aus dem Programmierung-Programm den passenden Kurs für deinen Stand zu finden.

Norbert Jansen

Norbert Jansen

Beratung & Inhouse

Plant mit dir Inhouse-Trainings, die auf eure Abläufe und euren Datenbestand zugeschnitten sind.

Das Modell an eurem eigenen Takt festmachen

In den Git- und Pipeline-Kursen bei cmt rechnet ihr durch, was euer Auslieferungstakt an Branches und an Automatisierung verlangt, und legt die Regeln so fest, dass sie nach vier Wochen noch gelten.