13 Branching-Strategien

Eine Branching-Strategie definiert, wie ein Team Branches organisiert, benennt und für verschiedene Zwecke nutzt. Sie ist eine Konvention darüber, welche Branches wann erstellt werden, wer welche Branches nutzt und wie diese Branches in der Entwicklungspipeline zusammenspielen. Im Gegensatz zu technischen Git-Mechanismen, die durch die Software vorgegeben sind, ist eine Branching-Strategie eine organisatorische Entscheidung – eine Vereinbarung im Team über den Workflow.

Git selbst erzwingt keine bestimmte Strategie. Es bietet leichtgewichtige Branches und flexible Mechanismen, aber wie diese genutzt werden, liegt in der Hand des Teams. Ein Zwei-Personen-Projekt kann mit einem einzigen Branch auskommen. Ein hundertköpfiges Team mit parallelen Releases benötigt komplexere Strukturen. Die richtige Strategie hängt von Projektgröße, Release-Frequenz, Team-Struktur und CI/CD-Infrastruktur ab.

13.1 Warum Branching-Strategien wichtig sind

Ohne explizite Strategie entsteht Chaos. Entwickler erstellen Branches nach Belieben, Namenskonventionen fehlen, es ist unklar, welcher Branch deployed werden sollte, und Konflikte häufen sich. Eine klare Strategie gibt Struktur:

Klarheit über Verantwortlichkeiten: Welcher Branch repräsentiert Production? Wo werden neue Features entwickelt? Wer darf in welchen Branch commiten?

Vorhersagbare CI/CD-Trigger: Moderne Pipelines reagieren auf Branch-Events. Eine Strategie definiert: Commits auf main triggern Production-Deployment, Commits auf Feature-Branches nur Tests, Tags triggern Releases.

Parallelität ohne Kollisionen: Mehrere Entwickler können gleichzeitig arbeiten, wenn klar ist, wer welchen Branch nutzt und wann Branches zusammengeführt werden.

Release-Management: Wie werden Versionen gebaut? Wie werden Hotfixes deployed? Eine Strategie beantwortet diese Fragen konsistent.

Eine gute Branching-Strategie ist dokumentiert, verstanden und wird gelebt. Sie ist nicht in Stein gemeißelt – Teams passen sie an, wenn sich Anforderungen ändern. Aber zu jedem Zeitpunkt sollte klar sein, welche Regeln gelten.

13.2 Grundsätzliche Branching-Muster

Bevor wir konkrete Strategien betrachten, die grundlegenden Muster, aus denen sie aufgebaut sind:

13.2.1 Long-Lived Branches: Die stabilen Hauptzweige

Long-lived Branches existieren über die gesamte Projektlaufzeit. Sie repräsentieren dauerhafte Zustände – typischerweise Production, Staging oder Development.

Beispiele: - main oder master: Der produktive Code - develop: Die aktuelle Entwicklungsarbeit - staging: Code im Staging-Environment

Diese Branches werden nicht gelöscht. Sie wachsen kontinuierlich durch Integration von Änderungen aus anderen Branches. Long-lived Branches sind die Rückgrat-Struktur des Repositories.

Charakteristik: Dauerhaft, geschützt (oft mit Zugriffsregeln), repräsentieren spezifische Environments oder Zustände.

13.2.2 Short-Lived Branches: Die temporären Arbeitszweige

Short-lived Branches werden für spezifische Aufgaben erstellt und nach Abschluss gelöscht. Typischerweise:

Diese Branches haben eine kurze Lebensdauer – Stunden bis Wochen. Nach Fertigstellung werden sie in einen long-lived Branch integriert und gelöscht.

Charakteristik: Temporär, aufgabenspezifisch, werden nach Integration gelöscht.

13.2.3 Release-Branches: Die Versionierungszweige

Release-Branches werden für die Vorbereitung spezifischer Releases erstellt. Während auf develop weiterentwickelt wird, stabilisiert sich der Release-Branch: Nur Bugfixes, keine neuen Features.

Beispiel: Für Version 2.0 wird release/2.0 erstellt. Das Team fixiert Bugs im Release-Branch, während neue Features für 2.1 bereits auf develop entwickelt werden. Nach dem Release wird der Release-Branch oft gelöscht oder archiviert.

Charakteristik: Zeitlich begrenzt (für eine Version), nur stabilisierende Änderungen, dienen der Release-Vorbereitung.

13.2.4 Environment-Branches: Die Umgebungs-Zuordnung

Manche Teams nutzen Branches, um Environments zu repräsentieren: - production: Was auf Production läuft - staging: Was auf Staging läuft - development: Was im Development-Environment läuft

Deployments werden durch Änderungen in diesen Branches getriggert. Ein Commit auf production deployed automatisch in Production.

Charakteristik: Environment-spezifisch, Deployments durch Branch-Updates getriggert, dauerhaft.

13.3 Etablierte Branching-Strategien

Aus diesen Mustern haben sich standardisierte Strategien entwickelt. Jede hat ihre Philosophie, Stärken und Schwächen.

13.3.1 Git Flow: Die strukturierte Strategie

Git Flow (Vincent Driessen, 2010) ist eine formale, strukturierte Strategie mit klar definierten Branch-Typen und -Regeln.

Branch-Struktur: - main: Production-Code, jeder Commit ist ein Release - develop: Integration-Branch für Features - feature/*: Short-lived Branches für neue Features (aus develop) - release/*: Vorbereitung neuer Releases (aus develop) - hotfix/*: Dringende Production-Fixes (aus main)

gitGraph
    commit id: "Initial"
    branch develop
    commit id: "Dev work"
    branch feature/new-feature
    commit id: "Feature A"
    commit id: "Feature B"
    checkout develop
    merge feature/new-feature
    branch release/1.0
    commit id: "RC fixes"
    checkout main
    merge release/1.0 tag: "v1.0.0"
    checkout develop
    merge release/1.0
    branch hotfix/critical
    checkout main
    merge hotfix/critical tag: "v1.0.1"
    checkout develop
    merge hotfix/critical

Workflow: 1. Features werden in feature/*-Branches entwickelt 2. Fertige Features werden in develop integriert 3. Für ein Release wird release/X.Y von develop abgezweigt 4. Der Release-Branch wird stabilisiert (nur Bugfixes) 5. Der Release wird in main integriert und getaggt 6. main und develop bleiben synchron

Hotfix-Flow: Dringende Fixes werden aus main abgezweigt, gefixxt, in main UND develop integriert.

Stärken: - Sehr strukturiert, klare Regeln - Trennung von Production (main) und Development (develop) - Gut für Projekte mit geplanten Releases - Parallele Release-Vorbereitung möglich

Schwächen: - Komplex für kleine Teams oder schnelle Releases - Zwei long-lived Branches (main und develop) erhöhen Synchronisationsaufwand - Kann zu langen Feature-Branches führen

Geeignet für: Größere Teams, Software mit Release-Zyklen, Projekte mit Wartungs-Releases (mehrere Versionen parallel).

13.3.2 GitHub Flow: Die minimalistische Strategie

GitHub Flow reduziert Komplexität radikal. Nur ein long-lived Branch (main), alles andere sind Feature-Branches.

Branch-Struktur: - main: Production-Code, immer deploybar - feature/* oder fix/*: Short-lived Branches für alles andere

Workflow: 1. Erstelle Feature-Branch von main 2. Committe Änderungen in Feature-Branch 3. Öffne Pull Request (Code Review) 4. Nach Approval: Integriere in main 5. main wird automatisch deployed 6. Lösche Feature-Branch

Kern-Prinzipien: - main ist immer deploybar - Jede Änderung geht durch einen Feature-Branch - Pull Requests erzwingen Code Review - Integration bedeutet Deployment

Stärken: - Extrem simpel, leicht zu lernen - Kurze Feedback-Zyklen - Fördert Continuous Deployment - Minimaler Overhead

Schwächen: - Kein explizites Release-Management - Schwierig bei mehreren parallelen Releases - Erfordert robuste automatisierte Tests - Nicht geeignet, wenn main nicht immer deploybar sein kann

Geeignet für: Web-Apps mit Continuous Deployment, kleine bis mittlere Teams, Projekte ohne feste Release-Zyklen.

13.3.3 GitLab Flow: Die umgebungsorientierte Strategie

GitLab Flow ist GitHubs Antwort auf die Lücke zwischen Git Flow und GitHub Flow. Es kombiniert Einfachheit mit Flexibilität für verschiedene Deployment-Szenarien.

Variante 1: Environment Branches

Für Projekte mit mehreren Deployment-Environments:

Branch-Struktur: - main: Entwicklung - staging: Staging-Environment - production: Production-Environment

Workflow: 1. Entwickle in Feature-Branches 2. Integriere in main (deployed zu Dev-Environment) 3. Wenn stabil: Integriere main in staging 4. Nach Validierung: Integriere staging in production

Jede Integration triggert Deployment in entsprechendes Environment.

Variante 2: Release Branches

Für Projekte mit versionierten Releases:

Branch-Struktur: - main: Aktuelle Entwicklung - 2-3-stable, 2-4-stable: Maintenance-Branches für Releases

Workflow: 1. Entwickle auf main 2. Für Release: Tag auf main (z.B. v2.4.0) 3. Falls Maintenance nötig: Erstelle 2-4-stable-Branch 4. Bugfixes gehen in Maintenance-Branch, werden zurück zu main portiert

Stärken: - Flexibel für verschiedene Szenarien - Environment-Branches machen Deployment-Status explizit - Einfacher als Git Flow, strukturierter als GitHub Flow

Schwächen: - Mehrere Varianten können verwirren - Environment-Branches können zu manuellen Integrations-Steps führen

Geeignet für: Projekte mit GitLab CI/CD, Multiple Environments, sowohl Continuous Deployment als auch versioned Releases.

13.3.4 Trunk-Based Development: Die Continuous Integration Strategie

Trunk-Based Development minimiert Branch-Lebensdauer extrem. Alle Entwickler committen direkt oder über sehr kurzlebige Branches in einen zentralen “Trunk” (main).

Branch-Struktur: - main (der “Trunk”): Einziger dauerhafter Branch - Sehr kurzlebige Feature-Branches (Stunden bis 1-2 Tage) – optional

Workflow: 1. Kleine Änderungen direkt in main ODER 2. Sehr kurzer Feature-Branch → schnelle Integration 3. Feature Flags für unfertige Features 4. Releases durch Tags auf main

Kern-Prinzipien: - Branches leben maximal 1-2 Tage - Integration mindestens täglich - Feature Flags statt lange Branches - Robuste automatisierte Tests essentiell

Stärken: - Minimale Merge-Komplexität - Erzwingt echte Continuous Integration - Schnelles Feedback - Keine lange divergierten Branches

Schwächen: - Erfordert Disziplin und Erfahrung - Feature Flags erhöhen Code-Komplexität - Schwierig für unerfahrene Teams - Benötigt exzellente Test-Coverage

Geeignet für: Erfahrene Teams, High-Frequency Deployment, Web Services, Teams mit starker CI/CD-Kultur.

13.4 CI/CD-Integration: Branches als Pipeline-Trigger

Moderne CI/CD-Systeme reagieren auf Git-Events. Die Branching-Strategie definiert, welche Events welche Pipeline-Steps triggern.

13.4.1 Branch-basierte Pipeline-Konfiguration

Typische Muster:

Branch-Pattern Triggered Actions Environment
main Build, Test, Deploy Production
develop Build, Test, Deploy Development
staging Build, Test, Deploy Staging
feature/* Build, Test (keine Deployment)
release/* Build, Test, Deploy Staging/Pre-Prod
hotfix/* Build, Test, Deploy (nach Approval) Production

Beispiel GitLab CI-Konfiguration (konzeptuell):

# Build & Test auf allen Branches
build:
  script: npm run build
  
test:
  script: npm test

# Deploy nur auf spezifischen Branches  
deploy_production:
  script: deploy.sh production
  only:
    - main

deploy_staging:
  script: deploy.sh staging
  only:
    - staging
    - /^release\/.*/

deploy_development:
  script: deploy.sh dev
  only:
    - develop

13.4.2 Tag-basierte Releases

Viele Teams nutzen Tags für Release-Trigger statt Branches:

Vorteile: - Klare Release-Markierung - Branches bleiben simpler - Semantic Versioning durch Tag-Namen

Beispiel:

release:
  script: build_and_deploy.sh
  only:
    - tags
  except:
    - branches

Nur Tags triggern diese Pipeline, nicht Branch-Commits.

13.4.3 Merge Request Pipelines

Feature-Branches triggern oft spezielle Merge Request Pipelines: - Preview-Deployments - Extended Tests - Code Quality Checks - Security Scans

Diese Pipelines laufen bei jedem Commit im MR, geben kontinuierliches Feedback, verhindern Integration von problematischem Code.

13.5 Auswahl der richtigen Strategie

Es gibt keine universell beste Strategie. Die Wahl hängt von mehreren Faktoren ab:

13.5.1 Team-Größe

Klein (2-5 Entwickler): GitHub Flow oder Trunk-Based Development. Minimaler Overhead, schnelle Integration.

Mittel (5-20): GitLab Flow oder vereinfachter Git Flow. Etwas mehr Struktur, klare Verantwortlichkeiten.

Groß (20+): Git Flow oder strukturierter GitLab Flow. Formale Regeln nötig, parallele Arbeit an vielen Features.

13.5.2 Release-Frequenz

Continuous (mehrmals täglich): GitHub Flow oder Trunk-Based. main ist immer Production.

Regelmäßig (wöchentlich/monatlich): GitLab Flow mit Environment-Branches oder GitHub Flow mit Release-Tags.

Geplant (quartalsweise): Git Flow mit Release-Branches. Zeit für Stabilisierung zwischen Releases.

Multiple Versions: Git Flow mit Maintenance-Branches. Support für mehrere Versionen parallel.

13.5.3 Deployment-Komplexität

Single Environment: GitHub Flow genügt. main = Production.

Multiple Environments: GitLab Flow mit Environment-Branches. Explizite Promotion zwischen Environments.

On-Premise + Cloud: Git Flow oder GitLab Flow. Verschiedene Branches für verschiedene Deployment-Targets.

13.5.4 Regulatorische Anforderungen

Hoch reguliert (Finance, Healthcare): Git Flow. Klare Trennung, Audit-Trail, manuelle Approvals.

Standard: GitLab Flow. Balance zwischen Kontrolle und Geschwindigkeit.

Minimal: GitHub Flow oder Trunk-Based. Schnelligkeit über formale Prozesse.

13.5.5 Team-Erfahrung

Junior-lastig: Git Flow oder GitLab Flow. Klare Regeln, schwer falsch zu machen.

Gemischt: GitLab Flow. Flexibel genug, nicht zu komplex.

Senior-lastig: Trunk-Based oder GitHub Flow. Vertrauen auf Team-Kompetenz.

13.6 Hybrid-Ansätze und Anpassungen

Keine Strategie muss dogmatisch befolgt werden. Teams passen an:

Git Flow Lite: Git Flow ohne develop-Branch. Features gehen direkt in main, Release-Branches für Stabilisierung.

GitHub Flow mit Staging: GitHub Flow + staging-Branch für Pre-Production-Validierung.

Trunk-Based mit Long-Lived Features: Trunk-Based Development, aber lange Features in Branches mit Feature Flags.

Wichtig: Anpassungen müssen dokumentiert und kommuniziert sein. Ein “fast wie GitHub Flow, aber…” ist verwirrend.

13.7 Evolutionäre Strategien

Branching-Strategien sind nicht statisch. Sie entwickeln sich mit dem Projekt:

Phase 1 (Early Development): GitHub Flow. Schnell iterieren, wenig Overhead.

Phase 2 (Growth): Übergang zu GitLab Flow. Mehr Entwickler, Environment-Branches für Stabilität.

Phase 3 (Maturity): Eventuell Git Flow. Multiple Releases, Maintenance-Branches, formale Prozesse.

Phase 4 (Optimization): Zurück zu Trunk-Based. Team ist erfahren, Prozesse automatisiert.

Regelmäßige Retrospektiven: Funktioniert unsere Strategie noch? Zu komplex? Zu simpel? Anpassen nach Bedarf.

13.8 Best Practices unabhängig von der Strategie

Unabhängig von der gewählten Strategie, einige universelle Prinzipien:

Dokumentation: Schreibe die Strategie auf. Neue Teammitglieder müssen sie verstehen können.

Branch-Naming: Konsistente Namen. feature/, bugfix/, hotfix/, release/ als Präfixe. Include Ticket-Nummer: feature/JIRA-123-new-login.

Branch-Protection: Long-lived Branches schützen. Keine direkten Commits, nur über Pull Requests. Require Reviews.

Short-Lived Branches: Feature-Branches sollten Tage, nicht Wochen leben. Je länger, desto schwieriger die Integration.

Regelmäßige Integration: Auch in Feature-Branches regelmäßig vom Haupt-Branch pullen. Verhindert große Konflikte.

Clean-Up: Gelöschte Branches aufräumen. Alte Branches verwirren und blähen das Repository.

CI/CD First: Strategie sollte CI/CD-Pipelines optimal nutzen. Branches, die nichts triggern, bringen keinen Wert.

Communication: Große Merges kommunizieren. “Ich merge Feature X in main heute Nachmittag” verhindert Überraschungen.

13.9 Anti-Patterns: Was zu vermeiden ist

Zu viele Long-Lived Branches: Mehr als 3-4 dauerhafte Branches werden unübersichtlich.

Sehr lange Feature-Branches: Branches, die Wochen oder Monate leben, führen zu “Integration Hell”.

Inkonsistente Naming: new-feature, feature_login, FEAT-signup – Chaos.

Direkte Commits auf Production-Branch: main sollte geschützt sein. Änderungen nur über Merges.

Vergessene Branches: Hunderte alter Feature-Branches, die niemand löscht. Regelmäßig aufräumen.

Überengineering: Git Flow mit 7 Branch-Typen für ein 3-Personen-Team ist Overkill.

Keine Strategie: “Jeder macht, was er will” führt zu Chaos.

13.10 Zusammenfassung: Strategie als Team-Entscheidung

Eine Branching-Strategie ist keine technische Notwendigkeit – Git funktioniert mit beliebigen Workflows. Sie ist eine organisatorische Entscheidung, die Klarheit und Effizienz bringt.

Die “beste” Strategie existiert nicht. Git Flow ist nicht “besser” als GitHub Flow – sie sind für unterschiedliche Kontexte optimiert. Die richtige Wahl hängt von Team, Projekt, Release-Prozessen und Tooling ab.

Beginne simpel. Ein neues Projekt kann mit GitHub Flow starten. Wenn Komplexität wächst, passe an. Wechsel zu GitLab Flow oder Git Flow, wenn nötig. Oder bleibe bei GitHub Flow, wenn es funktioniert.

Dokumentiere die Entscheidung. Kommuniziere die Regeln. Leben die Strategie konsequent. Evaluiere regelmäßig. Sei bereit anzupassen.

Am Ende ist die beste Branching-Strategie die, die das Team versteht, befolgt und die die Entwicklung beschleunigt statt bremst. Technische Perfektion ist weniger wichtig als praktische Tauglichkeit.

Branches sind billig, flexibel, mächtig. Die Strategie definiert, wie diese Macht strukturiert genutzt wird. Eine gute Strategie macht Branches zu einem Enabler paralleler, effizienter Entwicklung. Eine schlechte macht sie zur Quelle von Frustration und Konflikten.

Wähle weise, aber dogmatisch. Die Strategie dient dem Team, nicht umgekehrt.