Enterprise GIT Workflows – GitFlow 2.0 – Branch per Feature

In wahrscheinlich 90% aller Projekte die heute mit GIT arbeiten wird erfolgreich das bekannte Gitflow-Branching Modell eingesetzt und das zurecht. Das Modell ist praktisch, einfach zu verstehen und leicht anpassbar.

Doch es gibt andere Branching-Modelle die komplexer als das Gitflow Modell sind und nur in bestimmten Fällen tatsächlich Sinn machen.

Ein Modell, das ich heute vorstellen möchte ist das sogenannte Branch-Per-Feature Modell (den offiziellen Namen kenne ich nicht, aber unter diesem Namen ist dieses Modell bekannt, weswegen ich hier ebenfalls diesen Namen bzw. die Abkürzung BPF verwenden werde).

Urpsprünglich wurde das Modell von Adam Dymitruk formuliert und von ACQUIA enterprise-tauglich beschrieben. Das Modell ist aber nicht trivial und deswegen fasse ich es hier nochmals zusammen.

Als Vorwissen für die Arbeit mit diesem Modell sollte man sich kurz mit der Idee eines verteilten ReReRe-Caches vertraut machen.

Es gibt eine interessante Skriptsammlung, die für einen ersten Testlauf mit dem BPF-Modell verwendet werden kann. Für die Verwendung in einem Projekt kann ich die Skriptsammlung jedoch nicht empfehlen, da einige Einschränkungen in Kauf genommen werden müssen.

  • Basiert auf GIT Hooks
  • Verwendet Orphan-Branches für Shared-ReReRe Cache
  • Basiert auf der Annahme, dass alle Merge-Commits auf dem Integration-Branch Features sind.

Wann setze ich das Modell ein?

BPF kann dann nützlich sein, wenn ihr eure Deploy-Artefakte dynamisch erzeugen müsst und zwar beliebig oft. Ein Beispiel ist die Erzeugung eines Release-Kandidaten aus Jira-Issues in einem bestimmten Status der auch das Zusammenpacken aller Branches die erfolgreich getestet wurden per Knopfdruck.

Zusätzlich bietet BPF außerdem die Möglichkeit, einzelne Features sogar nachträglich wieder aus dem Build-Prozess zu entfernen und eine neue Version zu liefern. So etwas ist mit Gitflow faktisch nicht möglich (ohne größeres verbiegen).

Stellen wir uns also einfach folgendes Szenario vor.

Ein Team entwickelt an einem interessanten Projekt und liefert regelmässig neue Versionen an einen großen Kundenstamm. Bevor Features aber ausgeliefert werden, werden sie auf einer Testumgebung getestet.  Features sollen generell so schnell wie möglich auf die Testumgebung und anschließend in Produktion gebracht werden.

Jeder Entwickler hat die Möglichkeit, sein Feature auf die Integrationsumgebung zu bringen.

Die Qualität in der Entwicklung ist generell hoch. Es kommt aber natürlich trotzdem vor, dass Features nicht abgenommen werden, weil sie manchmal einfach unzureichend spezifiziert waren oder sich in seltenen Fällen ein Fehler eingeschlichen hat.

Bisher wurde immer so gearbeitet, dass dann für den Bug ein Bugfix geliefert worden ist, der in der nächsten Version bereitgestellt wurde. Je nach Schwere des Bugs konnte hierbei aber das Testen auf der Integrationsumgebung behindert werden und bis zur Lieferung des Bugfixes waren alle Tester blockiert.

Manche Features waren auch so problembehaftet, dass sie von der Integrationsumgebung nicht ausgeliefert werden sollten. In diesen Fällen mussten Teile der Implementierung zurückgenommen werden oder nachträglich Feature-Flags eingebaut werden um das Feature technisch zwar auszuliefern aber den Kunden noch nicht zur Verfügung zu stellen.

Mit einfachen Bordmitteln ist dies nicht ohne Weiteres zu realisieren. Das Team entschließt sich also, mit Git BPF zu arbeiten. BPF kann in gewissem Sinn als Weiterentwicklung von GitFlow-Modells betrachtet werden geht allerdings noch einige Schritte weiter.

Die Version die auf der Testumgebung getestet wird kann auf Knopfdruck erzeugt werden.

Features können ein- und wieder ausgeschaltet werden. Dies geschieht nicht im Sourcecode über Feature-Flags oder ähnliches sondern bereits über die Versionskontrolle. Es kann also am Montag eine Testversion mit Feature-1, Feature-2 und Feature-3 erzeugt werden, am Dienstag wird festgestellt, dass Feature-3 noch nicht  fertig ist und auf Knopfdruck wird eine neue Version mit Feature-1 und Feature-2, aber ohne Feature-3 erzeugt und auf die Testumgebung gespielt.

Ein Beispiel für die Verwendung des Workflows findet sich in folgendem Video.

Beschreibung des Workflows

Nehmen wir an, wir arbeiten in einem interessanten Projekt und überlegen uns, folgende Branches zu verwenden.

Auf dem MASTER-Branch findet die tägliche Entwicklung statt. Hier werden die meisten Commits gemacht.

Der BUILD-Branch dient nur der kontinuierlichen Integration. Hier werden nach belieben Features gemerged. Diese Version wird nicht deployt. Dazu später mehr.

Der INTEGRATION-Branch wird auf eine Integrations / Testumgebung deployt und dient zum Test / zur Stabilisierung.

Der RELEASE-Branch hält die aktuell jeweils in der Produktivumgebung deployte Version.  Der Release Branch kann auch als optional angesehen werden.

BPF Branches

Die Entwicklung findet genau wie im GitFlow-Modell ausschließlich auf Feature-Branches statt, die vom master (dem aktuellen Entwicklungsstand) weggebrancht werden.

bpf.002

Jeder Entwickler merged so oft wie möglich (idealerweise einmal täglich) von seinem Feature-Branch auf den Build-Branch. Dies dient der Integration mit anderen Features, die ebenfalls auf den Build-Branch gemerged wurden. Ziel ist es, möglichst früh zu reintegrieren und mögliches Konfliktpotential zwischen Stories und Features aufzudecken.

Der Build Branch wird nirgendwo deployt und ist ein Wegwerf-Branch, da zu keinem Zeitpunkt feststeht, welche Features auf den Branch gemerged wurden.

bpf.004

Merge Konflikte werden im Shared-ReReRe-Cache gespeichert und stehen ab diesem Zeitpunkt allen Entwicklern (und ggf. dem Jenkins) zur Verfügung.

Im unteren Beispiel merged der Entwickler das Feature-2 zum ersten Mal auf den Build-Branch und hat Merge-Konflikte aufzulösen. Der Entwickler löst diese Konflikte und speichert deren Lösung automatisch im Shared-ReReRe Cache.

bpf.006

Der Shared-ReReRe-Cache wird von allen Entwicklern geteilt.

bpf.007

Zu jedem Zeitpunkt kann der Stand des Integration-Branches  auf Knopfdruck neu erzeugt werden. ( ReCreate )

bpf.009

Die Entwicklung von Feature-1 enthielt in der ersten Version noch einen Fehler, also wird eine zweite Version gebaut, die auf den Integrationsbranch gemerged und anschließend auf die Testumgebung gespielt wird.

bpf.011

Die Entwicklung von Feature-2 ist mittlerweile auch abgeschlossen und der verantwortliche Entwickler erzeugt auf Knopfdruck ein neues Deployment-Artefakt das sowohl Feature-1 als auch Feature-2 enthält.

bpf.013

 Wichtig:

Üblicherweise profitiert das Team nicht allzu sehr von den Merges auf den Build branch. Die Entwicklungslinie des Build-Branches unterscheidet sich durch die Merges von der des Integration-Branches.

Das Deployment-Artefakt wird aus den Feature-Branches neu erzeugt. Fertige Features bleiben zunächst auf ihren Feature-Branches bestehen und werden nicht sofort zurückgeführt. Auf Knopfdruck (ReCreate) wird der bisherige Integration-Branch gelöscht, neu gezogen und alle Feature-Branches in der richtigen Reihenfolge auf den Integration-Branch gemerged.

Alle hierbei möglicherweise auftretenden Merge-Konflikte wurden bereits von den Entwicklern beim Merge auf den Build-Branch gelöst und die Lösung liegt allen im Shared-ReReRe-Cache vor. Es ist also keine manuelle Arbeit mehr vonnöten. Der Integrations-Branch kann vollautomatisch erzeugt werden.

bpf.014

bpf.015

Zum Zeitpunkt X definieren der Product Owner, die Tester und die Entwickler zusammen, dass der jetzige Stand auf dem Integrations-Branch bereit ist, den Kunden zur Verfügung gestellt zu werden. Es wird also ein neuer Release-Branch vom Integration-Branch gezogen und von diesem in Produktion geliefert.

bpf.016

Zu diesem Zeitpunkt wird auch der Release-Branch zurück in den master-Branch gemerged und alle ausgelieferten Feature-Branches können und sollten gelöscht werden. Der Stand wird getaggt.

bpf.018

Alle zu diesem Zeitpunkt nicht abgeschlossenen Features müssen jetzt ein Rebase gegen den neuen master-Stand machen um die neuen Änderungen zu bekommen. Merge-Konflikte werden wieder bei Auftreten über den Shared-ReReRe Cache gelöst.

bpf.019

Der Build-Branch zur kontinuierlichen Reintegration wird neu vom master-branch gezogen und alle Features sofort reintegriert.

bpf.021

Ein Hotfix verhält sich genau wie ein Feature-Branch. Er wird vom master-Branch gezogen, auf den build-Branch gemerged und anschließend per Knopfdruck auf die Testumgebung gespielt und in das Deploy-Artefakt aufgenommen.

bpf.023

Die Hotfix-Version kann nach kurzer Verifikation auf der Testumgebung schnell ausgeliefert werden.

bpf.025

Prinzipiell wäre auch nach der Hotfix-Version ein Rebase notwendig. Es muss allerdings nicht zwingend sofort durchgeführt werden, da es für die meisten Features unwahrscheinlich ist, dass sie mit einem Hotfix kollidieren.

bpf.026

Nicht immer arbeitet man nur mit einer Version. Oft hat man mehrere Versionen in Betrieb. Eine Version aktuell in Produktion, eine andere Version in System-Test beispielsweise. Vielleicht bestücken wir mehrere Stränge (beispielsweise für A-B-Testing).

In diesem Fällen gibt es für jede Version einen eigenen Build bzw. Integrationsbranch.

bpf.027

Vom master zweigt der Next-Branch ab, der beispielsweise für das zukünftige Release verwendet wird.

bpf.029

Der Ablauf ist genau gleich.

  1. Feature Branch
  2. Merge auf Build-Branch
  3. ReCreate für Integration-Branch
  4. Merge auf Release Branch

bpf.030

bpf.031

bpf.032

bpf.033  bpf.035

Nach jedem Produktionsrelease wird vom master auf den next-Branch gemerged.

bpf.036 bpf.037 bpf.038

Übrigens..

Branching Modelle wie Git Flow und Git BPF, die Arbeit mit Enterprise Tools wie Gerrit, Jenkins und die Atlassian Tools wie Stash sind Teil des Enterprise GIT Workshops. Wenn Sie mit GIT arbeiten möchten oder sogar bereits arbeiten würde ich mich über einen Anruf von Ihnen sehr freuen.

Effective Trainings & Consulting - Martin Dilger



Hat Ihnen dieser Blog-Eintrag gefallen? Ich stelle in diesem Blog Informationen über Tools, Frameworks und Werkzeuge zur Verfügung, die mich produktiver machen. Vielleicht kann ich auch Ihnen helfen, produktiver zu werden.


Ich unterstütze Sie als freier Mitarbeiter bei der Entwicklung von Software-Projekten, Agiler Arbeit sowie Schulungen / Fortbildungen.


Jeden Tag ein bisschen produktiver - ab heute