Long-Running Branches verstehen und synchron halten
Was sind Long-Running Branches?
Long-Running Branches (auch langlebige oder permanente Branches genannt) sind Branches, die über die gesamte Lebensdauer eines Projekts oder zumindest über längere Zeiträume hinweg bestehen bleiben – im Gegensatz zu kurzlebigen Feature-Branches, die nach dem Merge gelöscht werden.
Die typischen Long-Running Branches
In den meisten professionellen Projekten findest du folgende Struktur:
| Branch | Zweck | Lebensdauer |
|---|---|---|
main (oder master) |
Produktionscode – enthält nur stabilen, deploybaren Code | Permanent |
develop |
Integrationsbranch für die nächste Version – hier fließen Feature-Branches zusammen | Permanent |
release/* |
Vorbereitung einer neuen Version, nur noch Bugfixes erlaubt | Mittelfristig (Wochen) |
hotfix/* |
Kritische Fixes für Produktion | Kurzfristig (Tage) |
gitGraph
commit id: "Initial"
branch develop
commit id: "Setup"
branch feature/login
commit id: "Login-Form"
commit id: "Validation"
checkout develop
merge feature/login id: "Merge Login"
branch release/1.0
commit id: "Version bump"
commit id: "Bugfix"
checkout main
merge release/1.0 id: "Release 1.0" tag: "v1.0.0"
checkout develop
merge release/1.0 id: "Sync Release"
Warum ist Synchronisation so wichtig? ⚠️
Stell dir folgendes Szenario vor:
- Du erstellst am Montag einen Feature-Branch von
main - Du arbeitest zwei Wochen an deinem Feature
- In der Zwischenzeit wurden 50 Commits in
maingemergt (von anderen Entwicklern oder anderen Features) - Dein Feature-Branch ist jetzt zwei Wochen und 50 Commits hinter
main
Die Probleme, die entstehen können:
- Merge-Konflikte: Je länger du wartest, desto mehr Konflikte häufen sich an. Ein Merge nach zwei Wochen kann dutzende Konflikte haben, die du alle auf einmal lösen musst.
- Inkompatibilitäten: Vielleicht hat jemand eine Funktion geändert, die du verwendest. Dein Code funktioniert nicht mehr mit dem aktuellen Stand.
- Doppelte Arbeit: Möglicherweise wurde bereits Code geschrieben, den du gerade selbst implementierst.
- Veraltete Basis: Du testest dein Feature gegen eine veraltete Codebasis – es könnte in Produktion anders funktionieren.
Die Lösung: Regelmäßige Synchronisation – idealerweise täglich oder zumindest bei jedem größeren Meilenstein in main.
Die zwei Strategien: Merge vs. Rebase
Es gibt zwei grundlegend verschiedene Ansätze, um Änderungen aus main in deinen Feature-Branch zu integrieren. Beide haben ihre Berechtigung, und die Wahl hängt von deinem Workflow und deinen Team-Konventionen ab.
Strategie 1: Merge (main → Feature-Branch)
Bei einem Merge werden die Änderungen aus main in deinen Feature-Branch integriert, wobei ein Merge-Commit entsteht, der beide Historien verbindet.
gitGraph
commit id: "A"
commit id: "B"
branch feature/shop
commit id: "F1"
commit id: "F2"
checkout main
commit id: "C"
commit id: "D"
checkout feature/shop
merge main id: "Merge main" type: HIGHLIGHT
commit id: "F3"
Was passiert hier?
- Dein Feature-Branch enthält nach dem Merge sowohl deine Commits (F1, F2) als auch die neuen Commits aus
main(C, D) - Ein Merge-Commit dokumentiert, wann du synchronisiert hast
- Die ursprüngliche Historie bleibt vollständig erhalten
Strategie 2: Rebase (Feature-Branch auf main)
Bei einem Rebase werden deine Feature-Commits „abgelöst" und auf die Spitze von main neu aufgesetzt. Es entsteht eine lineare Historie ohne Merge-Commits.
gitGraph
commit id: "A"
commit id: "B"
commit id: "C"
commit id: "D"
branch feature/shop
commit id: "F1 neu" type: HIGHLIGHT
commit id: "F2 neu" type: HIGHLIGHT
commit id: "F3"
Was passiert hier?
- Deine Commits werden „verschoben" – sie basieren jetzt auf dem aktuellen Stand von
main - Es entstehen technisch gesehen neue Commits (mit neuen Hashes), auch wenn der Inhalt identisch ist
- Die Historie sieht aus, als hättest du erst jetzt mit deiner Arbeit begonnen
Ausführliche Anleitung: Synchronisation mit Merge
Szenario
Du arbeitest an einem Feature-Branch feature/newsletter und möchtest die neuesten Änderungen aus main integrieren.
Schritt 1: Sicherstellen, dass du einen sauberen Arbeitsstand hast
Bevor du irgendetwas synchronisierst, sollte dein Working Directory „sauber" sein – also keine uncommitteten Änderungen enthalten.
In PhpStorm prüfen:
- Schau in der linken unteren Ecke auf den „Git"-Tab
- Unter „Local Changes" sollten keine Dateien stehen
Falls du unfertige Änderungen hast, nutze Stash:
# Terminal-Variante
git stash push -m "WIP: Newsletter-Formular"
In PhpStorm:
- Menü: Git → Uncommitted Changes → Stash Changes...
- Gib eine aussagekräftige Nachricht ein
- Klicke Create Stash
Schritt 2: Den neuesten Stand von main holen (Fetch)
Zuerst musst du sicherstellen, dass dein lokales Repository die neuesten Informationen vom Remote hat.
In PhpStorm:
- Klicke auf das blaue ↓ Pfeil-Symbol in der Toolbar (oder Ctrl+T / Cmd+T)
- Oder: Menü Git → Fetch
Dies aktualisiert origin/main mit dem Stand auf GitHub, ohne deinen lokalen main-Branch zu verändern.
Schritt 3: main in deinen Feature-Branch mergen
Methode A: Über das Git-Log in PhpStorm (empfohlen)
- Öffne das Git-Log: Klicke unten auf den Tab „Git" und dann auf „Log"
- Stelle sicher, dass du auf deinem Feature-Branch bist (sichtbar unten rechts in der Statusleiste)
- Im Log siehst du alle Branches – finde
origin/main - Rechtsklick auf den neuesten Commit von
origin/main - Wähle „Merge 'origin/main' into 'feature/newsletter'"
flowchart TD
A["1. Git-Log offnen\n Ansicht: Git - Log"] --> B["2. Branch prufen\n Bist du auf feature/newsletter?"]
B --> C["3. origin/main finden\n Im Log-Graphen"]
C --> D["4. Rechtsklick auf\n neuesten Commit"]
D --> E["5. Merge origin/main\n into feature/newsletter"]
E --> F{Konflikte?}
F -->|Ja| G["Konflikte losen\n 3-Way-Merge-Editor"]
F -->|Nein| H["Fertig!\n Merge-Commit erstellt"]
G --> H
style A fill:#e1f5fe,color:#000000
style E fill:#fff3e0,color:#000000
style H fill:#e8f5e9,color:#000000
Methode B: Über das Branch-Menü
- Klicke unten rechts auf den aktuellen Branch-Namen (z.B.
feature/newsletter) - Im Dropdown: Finde „origin/main" unter „Remote Branches"
- Klicke darauf und wähle „Merge into Current"
Methode C: Über das Hauptmenü
- Menü: Git → Merge...
- Wähle
origin/mainaus der Liste - Klicke Merge
Schritt 4: Konflikte lösen (falls vorhanden)
Wenn es Konflikte gibt, öffnet PhpStorm automatisch ein Dialogfenster „Files Merged with Conflicts":
- Klicke auf „Merge..." neben der konfliktbehafteten Datei
- Der 3-Way-Merge-Editor öffnet sich:
- Links: Deine Version (feature/newsletter)
- Rechts: Ihre Version (main)
- Mitte: Das Ergebnis, das du zusammenbaust
- Nutze die
>>und<<Buttons, um Änderungen zu übernehmen - Wenn du fertig bist: Apply
- Nachdem alle Konflikte gelöst sind: Der Merge-Commit wird automatisch erstellt
Schritt 5: Ergebnis überprüfen
Nach dem Merge solltest du kurz prüfen:
- Schau ins Git-Log: Du siehst jetzt einen Merge-Commit mit zwei Eltern-Commits
- Führe deine Tests aus: Stelle sicher, dass alles noch funktioniert
- Pushe deinen Branch:
Ctrl+Shift+Koder Git → Push
Terminal-Befehle (zur Referenz)
# 1. Auf Feature-Branch wechseln (falls nicht schon dort)
git checkout feature/newsletter
# 2. Neueste Daten vom Remote holen
git fetch origin
# 3. main in Feature-Branch mergen
git merge origin/main
# 4. Bei Konflikten: Nach dem manuellen Lösen
git add .
git commit # Merge-Commit abschließen
# 5. Pushen
git push origin feature/newsletter
Ausführliche Anleitung: Synchronisation mit Rebase
Wichtiger Hinweis vorab ⚠️
Rebase schreibt die Historie um – deine Commits bekommen neue SHA-Hashes. Das bedeutet:
- Wenn du deinen Branch noch nicht gepusht hast: Kein Problem, rebase frei.
- Wenn du schon gepusht hast und alleine am Branch arbeitest: Möglich, aber du brauchst
git push --force-with-lease. - Wenn andere auch an deinem Branch arbeiten: 🚫 Kein Rebase! Du würdest die Arbeit der anderen durcheinanderbringen.
Szenario
Du arbeitest an feature/checkout und möchtest deine Commits auf den aktuellen Stand von main neu aufsetzen.
Schritt 1: Vorbereitung (wie beim Merge)
- Sicherstellen, dass das Working Directory sauber ist
- Unfertige Änderungen ggf. stashen
git fetchausführen, umorigin/mainzu aktualisieren
Schritt 2: Rebase in PhpStorm starten
Methode A: Über das Git-Menü (empfohlen für Einsteiger)
- Stelle sicher, dass du auf deinem Feature-Branch bist
- Menü: Git → Rebase...
- Im Dialog „Rebase":
- „Onto": Wähle
origin/main - Die anderen Optionen kannst du auf Standard lassen
- „Onto": Wähle
- Klicke Rebase
Methode B: Über das Branch-Popup
- Klicke unten rechts auf deinen Branch-Namen
- Finde
origin/mainunter „Remote Branches" - Klicke darauf und wähle „Rebase Current onto Selected"
Methode C: Über das Git-Log
- Öffne das Git-Log
- Rechtsklick auf den neuesten Commit von
origin/main - Wähle „Rebase 'feature/checkout' onto 'origin/main'"
Schritt 3: Konflikte während des Rebases lösen
Beim Rebase werden deine Commits einzeln auf main neu angewendet. Das bedeutet: Wenn es Konflikte gibt, musst du sie für jeden betroffenen Commit einzeln lösen.
Der Ablauf bei Konflikten:
flowchart TD
A["Rebase starten"] --> B["Commit 1 anwenden"]
B --> C{Konflikt?}
C -->|Nein| D["Commit 2 anwenden"]
C -->|Ja| E["Konflikt losen"]
E --> F["Git - Rebase - Continue"]
F --> D
D --> G{Konflikt?}
G -->|Nein| H["Commit 3 anwenden"]
G -->|Ja| I["Konflikt losen"]
I --> J["Git - Rebase - Continue"]
J --> H
H --> K["Rebase abgeschlossen!"]
style A fill:#e1f5fe,color:#000000
style E fill:#ffcccc,color:#000000
style I fill:#ffcccc,color:#000000
style K fill:#e8f5e9,color:#000000
Konkret in PhpStorm:
- Bei einem Konflikt zeigt PhpStorm eine Notification: „Rebase stopped due to conflicts"
- Löse die Konflikte im 3-Way-Merge-Editor (wie beim Merge)
- Nach dem Lösen: Git → Rebase → Continue
- PhpStorm wendet den nächsten Commit an
- Wiederhole, bis alle Commits neu angewendet wurden
Wenn du abbrechen möchtest:
- Git → Rebase → Abort – Stellt den Zustand vor dem Rebase wieder her
Schritt 4: Force-Push (falls bereits gepusht)
Da Rebase neue Commits erstellt, musst du mit --force pushen, wenn der Branch bereits auf GitHub existiert.
In PhpStorm:
Ctrl+Shift+K(oder Git → Push)- PhpStorm zeigt dir, dass ein Force-Push nötig ist
- Klicke auf den kleinen Pfeil neben „Push" und wähle „Force Push"
Besser: Verwende --force-with-lease:
git push --force-with-lease origin feature/checkout
Dies ist sicherer als --force, weil es prüft, ob jemand anderes in der Zwischenzeit gepusht hat.
In PhpStorm aktivieren:
- Settings → Version Control → Git
- Aktiviere „Use --force-with-lease for force push"
Terminal-Befehle (zur Referenz)
# 1. Auf Feature-Branch wechseln
git checkout feature/checkout
# 2. Fetch
git fetch origin
# 3. Rebase starten
git rebase origin/main
# 4a. Bei Konflikten: Nach dem Lösen weitermachen
git add .
git rebase --continue
# 4b. Oder abbrechen
git rebase --abort
# 5. Force-Push (nur wenn schon gepusht)
git push --force-with-lease origin feature/checkout
Merge vs. Rebase: Direkter Vergleich
| Aspekt | Merge | Rebase |
|---|---|---|
| Historie | Bewahrt die komplette, echte Historie mit allen Verzweigungen | Erzeugt eine lineare, „saubere" Historie |
| Merge-Commits | Ja, ein Merge-Commit pro Synchronisation | Nein, keine zusätzlichen Commits |
| Commit-Hashes | Bleiben unverändert | Ändern sich (neue Commits) |
| Konfliktlösung | Alle Konflikte auf einmal | Konflikte pro Commit einzeln |
| Force-Push nötig? | Nein | Ja, wenn Branch bereits gepusht |
| Sicher bei Team-Branches? | ✅ Ja | ⚠️ Nur mit Vorsicht |
| Nachvollziehbarkeit | Sehr gut (wann wurde was integriert?) | Geschichte wird „umgeschrieben" |
| Komplexität | Einfacher | Komplexer |
Visuelle Gegenüberstellung
Nach mehreren Merge-Synchronisationen:
main: A───B───C───D───E───F───G
\ \ \
feature: X───Y───M───Z───M───W
↑ ↑
Merge-Commits
Nach Rebase (vor dem finalen Merge):
main: A───B───C───D───E───F───G
\
feature: X'──Y'──Z'──W'
↑
Neu aufgesetzte Commits
Welche Strategie solltest du wählen?
Wähle Merge, wenn...
- 👥 Mehrere Personen am selben Branch arbeiten – Rebase würde deren Arbeit zerstören
- 📜 Du eine vollständige Audit-Trail brauchst – z.B. in regulierten Umgebungen
- 🆕 Du noch unsicher mit Git bist – Merge ist verzeihender
- 🔀 Dein Team Merge bevorzugt – Konsistenz ist wichtiger als persönliche Vorliebe
Wähle Rebase, wenn...
- 👤 Du alleine am Feature-Branch arbeitest
- ✨ Du eine saubere, lineare Historie bevorzugst
- 📖 Dein Team „Rebase before Merge" als Konvention hat
- 🧹 Du deine Commits vor dem PR aufräumen möchtest (Interactive Rebase)
Der Kompromiss: „Rebase lokal, Merge für Integration"
Viele Teams nutzen eine hybride Strategie:
- Während der Feature-Entwicklung: Rebase nutzen, um den Feature-Branch aktuell zu halten (solange nicht gepusht oder alleine am Branch)
- Für den finalen Merge: Einen normalen Merge (oder Squash-Merge) in
mainmachen
flowchart LR
A["Feature-Branch\n erstellen"] --> B["Entwickeln"]
B --> C{"Neue Commits\n in main?"}
C -->|Ja| D["Rebase auf main\n lokal"]
D --> B
C -->|Nein| E{"Feature\n fertig?"}
E -->|Nein| B
E -->|Ja| F["Pull Request\n erstellen"]
F --> G["Code Review"]
G --> H["Merge PR\n in main"]
style D fill:#fff3e0,color:#000000
style H fill:#e8f5e9,color:#000000
Praktische Tipps für die tägliche Arbeit 💡
Tipp 1: Synchronisiere regelmäßig
Mache es dir zur Gewohnheit, mindestens einmal täglich (oder bei jedem PR, der in main gemergt wird) zu synchronisieren:
# Schneller Check am Morgen
git fetch origin
git log HEAD..origin/main --oneline
# Zeigt dir, wie viele Commits du "hinterher" bist
In PhpStorm siehst du das im Git-Log: Wenn origin/main weiter ist als der Verzweigungspunkt deines Branches, ist es Zeit zu synchronisieren.
Tipp 2: Nutze PhpStorms „Update Project"
Der schnellste Weg für den täglichen Workflow:
Ctrl+T(oder Git → Update Project)- Wähle Rebase oder Merge (du kannst eine Standardeinstellung setzen)
- PhpStorm führt Fetch + Merge/Rebase in einem Schritt aus
Tipp 3: Konfiguriere deine Standard-Strategie
In PhpStorm:
- Settings → Version Control → Git
- Unter „Update Method": Wähle deine bevorzugte Methode
Global in Git:
# Für Rebase als Standard
git config --global pull.rebase true
# Für Merge als Standard (default)
git config --global pull.rebase false
Tipp 4: Erstelle einen Alias für den Workflow
Wenn du häufig synchronisierst, erstelle einen Git-Alias:
# In ~/.gitconfig oder via Befehl:
git config --global alias.sync-main '!git fetch origin && git rebase origin/main'
# Nutzung:
git sync-main
Tipp 5: Kommuniziere mit deinem Team
Die wichtigste „Technik" ist eigentlich keine technische: Sprich mit deinem Team!
- Einigt euch auf eine Strategie (Merge oder Rebase)
- Dokumentiert sie in der
CONTRIBUTING.md - Nutzt Branch Protection Rules, um die Strategie durchzusetzen
Zusammenfassung 📋
Long-Running Branches sind permanente Branches wie main und develop, die als Integrationspunkte dienen und niemals gelöscht werden.
Regelmäßige Synchronisation ist essentiell, um:
- Merge-Konflikte klein zu halten
- Gegen aktuellen Code zu entwickeln
- Integrationsprobleme früh zu erkennen
Zwei Strategien stehen zur Verfügung:
-
Merge (
git merge origin/main):- Erzeugt Merge-Commits
- Bewahrt die echte Historie
- Sicher für Team-Branches
-
Rebase (
git rebase origin/main):- Erzeugt lineare Historie
- Ändert Commit-Hashes (Force-Push nötig)
- Nur für Branches, an denen du alleine arbeitest
Die beste Strategie ist die, auf die sich dein Team einigt und die konsistent angewendet wird.