Git-Workflows im Überblick Zusammenarbeit mit Git – aber wie?
Anbieter zum Thema
Einfachheit? Oder doch eher Code-Qualität? Für Git gibt es unterschiedliche etablierte Worfklow-Modelle mit Vor- und Nachteilen – und nicht immer sind sie in der Praxis so strikt getrennt.

Obwohl dieser Artikel unter dem Stichwort „Zusammenarbeit“ steht: Auch für private Repositories, die ganz allein bearbeitet werden, sind die hier vorgestellten Konzepte interessant. Denn mindestens einen Punkt möchten wohl alle Git-User immer umschiffen: die Merge-Hölle.
Stundenlang Diffs durchzugehen und mal diese, mal jene Änderung zu akzeptieren, ist lästig. Erst kürzlich haben wir Ihnen gezeigt, wie clevere Merge-Strategien das Zusammenführen von Code-Branches deutlich vereinfachen. Das ist gut und schön, setzt aber dort an, wo das Kind schon in den Brunnen gefallen ist. Hier geht es eher um den Schritt davor, die Frage, wie genau Kontributoren ihre Beiträge in Form von Commits überhaupt ins Projekt einbringen und wie aus diesen letztlich ein Release werden kann.
Die eine richtige Variante gibt es dabei nicht. Es hängt von der Größe des Teams ab, den individuell sehr unterschiedlichen Fähigkeiten, der Komplexität einzelner Aufgaben und des gesamten Projekts, die Zugänglichkeit für Dritte und so weiter. Und auf Git-Ebene selbst stellt sich ebenfalls die Frage nach Prioritäten: Eine saubere History? Möglichst wenig Branches? Kein unfertiger Code?
Basic-Workflow
Der Basis-Workflow (oft auch zentralisiert genannt) dürfte bei den meisten Projekten den Grundstein gelegt haben. In dieser Variante gibt es nur eine einzigen Branch (in der Regel Master oder Main genannt), der in einem zentralen Online-Repository liegt.
Der Workflow sieht dann meist so aus:
- Repository lokal klonen
- Änderungen vornehmen
- Änderungen committen (oder stashen)
- Repository pullen/updaten
- Änderungen wiederherstellen
- Änderungen Committen
- Commits pushen
Alle Projektteilnehmer pushen also direkt in den einzigen Branch des zentralen Repositorys. Der große Vorteil daran: Es gibt faktisch kein Branch-Management, Nutzer müssen sich mit relativ wenigen Git-Features auseinandersetzen.
Das kleine Problem hier: Lokale, eigene Commits können nur gepusht werden, wenn lokales und zentrales Repos auf dem gleichen Stand sind. Das sind sie in der Regel nicht, da auch andere Nutzer in das zentrale Repo pushen. Folglich aktualisiert man das lokale Repo im Alltag meist sehr regelmäßig per Pull und löst dann etwaige Merge-Konflikte lokal.
Das eigentliche Problem ist eher die Code-Basis: Tendenziell landen hier auch unfertige Features im einzigen Branch. Hat Entwicklerin A ihr Feature gerade gepusht und möchte einen Release erstellen, ist das keine gute Idee, wenn Entwickler B noch längst nicht fertig ist, seine bisherige Arbeit aber schon zum Beispiel als Beta gepusht hat. Das führt schnell zu Feature-Branches.
Feature-Branches-Workflow
Wie eben beschrieben, macht ein unfertiges Feature im Main-Branch schwierig bis praktisch unmöglich. Im nächstkomplexeren Workflow werden für einzelne, unabhängige Features separate Branches angelegt, über die dann mehrere Entwickler zusammenarbeiten können.
Ist eine Funktion fertig, wird der Feature-Branch in den Main-Branch überführt, so dass ein Release erstellt werden kann. Der Main-Branch enthält also im Optimalfall nur stabilen, publizierbaren Code. Das ist auch eine Voraussetzung für etwaige CI/CD-Pipelines, um beispielsweise einen Webservice stets als aktuelles Release zur Verfügung zu stellen.
Allerdings müssen dafür tendenziell noch einige Features des Git-Hosters, also GitHub, BitBucket, GitLab und so weiter, genutzt werden: Einen Merge der Feature-Branches sollten gegebenenfalls nur berechtigte Nutzer erledigen dürfen. Für jeden fertigen Feature-Branch wird also ein Pull Request erstellt, was auch gleich Möglichkeiten für Reviews und Diskussionen eröffnet
Developer-Branches-Workflow
Als Variante des Feature-Branch-Workflows gibt es auch die Developer-Branches, also eigene Arbeitszweige für alle beteiligten Personen. Im Grunde ist dies ein Mischmasch der beiden bisherigen Workflows: Wie beim Basis-Workflow können Entwickler an beliebigen Baustellen arbeiten, allerdings landen die Ergebnisse eben nicht direkt im Haupt-Branch mit dem „fertigen“ Code.
Arbeiten jedoch mehrere Personen in eigenen Branches an ein und demselben Feature, wird es kompliziert. Denn dann müssten entweder die Branches separat verschmolzen werden, bevor sie in den Main-Branch gelangen oder sie landen dort unabhängig und sorgen damit tendenziell für sehr einseitig verteilte Merge-Konflikte.
In kleineren Teams mit guter Kommunikation ist dies aber eine durchaus brauchbare und recht simple Variante. Allerdings insbesondere für eher einfache Projekte, etwa die Pflege einer Webseite.
GitFlow-Workflow
Bei GitFlow, der Name lässt es erahnen, geht es tatsächlich nicht um ein abstraktes Konzept, sondern einen ganz konkreten Rahmen. Die Kurzversion: Es handelt sich dabei um eine Erweiterung des Feature-Branch-Workflows, die zwischen Main- und Feature-Branches einen weiteren Branch namens Development einzieht.
Die Feature-Branches werden zudem weiter unterteilt in Branches für Features, Releases, Bugfixes und so weiter. Sind diese kurzlebigen Branches fertig, werden sie in den Development-Branch überführt, der auch als Basis für alle neuen Branches dient. Dieser Development-Code wird dann entsprechend wieder in den Main-Branch befördert.
Der Vorteil von GitFlow: Es ist ein sehr strukturiertes Konzept, das den Main-Branch komplett frei von verbuggtem Code halten sollte. Das liegt auch daran, dass sich Hierarchien gut abbilden lassen. Aber auch für größere Open-Source-Projekte ist es hilfreich, wenn zwar viele Personen den Entwicklungsstand in einem Branch abbilden können, aber nur die Projektverwaltung den Main-Branch pflegt.
Der Nachteil: Es ist ein recht starres Konzept und ob der vielen Vorgaben nicht einfach zu adaptieren. Und da Pull Requests/Merges hier gerne mal sehr umfangreich sind, kann dieser Punkt bisweilen sehr arbeitsintensiv sein. Vielen gilt es sogar als veraltet, selbst Vincent Driessen.
Der GitFlow-Erfinder hat mittlerweile den GitHub-Workflow als modernere Variante empfohlen; schließlich ist der Ur-Artikel zu GitFlow schon 13 Jahre alt und 2010 sah die Welt von Git, GitHub & Co. und vor allem CI/CD noch ganz anders aus. Für traditionelle Release-Zyklen bleiben die Vorteile aber bestehen und nach wie vor finden sich in manchen Git-GUIs konkrete Gitflow-Werkzeuge.
GitHub Flow
Den GitHub-eigenen Workflow kann man recht kurz zusammenfassen – wirklich Neues lässt sich hier auch kaum finden:
- Kurzlebige Branches für jedes unabhängige Vorhaben (etwa ein (Teil-)Feature)
- Separate Commits für jede unabhängige Änderung
- Pull Request erstellen
- Review und Änderungen im Branch durchführen
- Pull Request mergen
- Branch löschen
Im Grunde möchte GitHub hier also eigentlich nur vermitteln, dass es sinnvoll ist, einzelne, logisch unabhängige Arbeitsaufgaben jeweils in eigene Branches zu packen, via Pull Request auf GitHub.com zu prüfen und einzuarbeiten.
Im Gegensatz zum (traditionellen) Feature-Branch-Workflow werden Branches immerhin auch nicht optional direkt lokal per Merge kombiniert, sondern grundsätzlich via GitHub/Pull Request. Das ist tatsächlich eine gute Idee, zumal sich Branches dort – wie auch bei der Konkurrenz versteht sich – schützen lassen, etwa vom Löschen oder unpassenden Commits.
Trunk-based-Workflow
Zu Trunk-based Development (TBD) gibt es aktuell recht viel Literatur. Ganz einfach gedacht, meint Trunk-based kaum etwas anderes, als den Basis-Workflow mit ein paar Regeln. Auch hier geht es nur um den einen zentralen Branch – Trunk meint nichts anderes als Master oder Main. Allerdings wird hier im Sinne der Continuous Integration darauf gepocht, dass alle Entwickler mindestens einmal pro Tag ihr Arbeit per Push in den Main-Branch einfließen lassen und Commits eher klein gehalten werden.
Das Konzept hat zwei große Vorteile: Kein Overhead durch Branch-Management und kaum Merge-Konflikte durch viele kleine Commits und ständiges Aktualisieren. Und es wirft natürlich eine große Frage auf: Wie soll denn ein Release entstehen, wenn ständig unfertiger Code im einzigen zentralen Branch landet?
Nun, zum einen gibt es eben doch mehrere Branches – die reinen Release-Branches liegen dann aber, so die Idee, in den Händen eines expliziten Release-Managers. Diese Releases wiederum werden über Feature Flags realisiert – die Minimalerklärung: Unfertiger Code wird zwar gepusht, im Release aber erst dann manuell aktiviert, wenn der Code irgendwann fertig ist.
Und natürlich: Auch TBD wird in Varianten eingesetzt, die dann doch wieder auf weitere Branches zurückgreifen. Aber grundsätzlich bleibt die Entwicklung immer nah am Main-Branch. Und damit ist noch eine weitere Erfordernis klar: Vertrauen in die Entwickler! Wer Fehlertoleranz sucht, ist mit einem der Branching-Modell besser aufgestellt.
Forking Workflow
Zu guter Letzt noch ein Workflow, der aber eigentlich eher ein Zusatz ist – und eine Hinleitung zur Realität: Beim Forking bekommt einfach jeder Entwickler einen komplett eigene Kopie des gesamten Repositories und kann dann nach Belieben mit diesem Code arbeiten. So lassen sich zum Beispiel auch umfangreiche eigene Tests durchführen.
Sollen eigene Änderungen dann in das „echte“ Projekt einfließen, müssen sie als Branch zur Verfügung stehen, für den dann ein Pull Request erstellt wird. Insbesondere in der Open-Source-Realität ist Forking aber eigentlich ein separater Workflow, der für externe Dritte gedacht ist. Das Projektteam arbeitet beispielsweise mit Feature-Branches oder gar nur dem Basic-Workflow und Dritte können über PRs beitragen.
Am Ende ist bei den ganzen Workflows nur eines wichtig: Dass Sie sich Gedanken darüber machen, wie genau der perfekte Workflow für Ihr Projekt und Ihr Team aussieht! Tendenziell wird sich das über die Zeit noch ändern. Die vorgestellten Workflows sind daher vor allem für die Sensibilisierung oder als Brainstorming-Grundlage geeignet.
(ID:49224882)