Home

Anhang 1: Fortgeschrittene Git-Workflows und Konfliktmanagement

anhang git workflow rebase merge konfliktauflösung feature-branch best-practices

Einführung: Git-Herausforderungen in der realen Feature-Entwicklung

Während Sie an Ihrer ersten echten GitHub Classroom-Aufgabe arbeiten und Features mit dem Feature-Branch-Workflow implementieren, stoßen Sie auf Git-Herausforderungen, mit denen jeder professionelle Entwickler konfrontiert wird. Diese Anhang-Vorlesung behandelt die häufigsten Git-Probleme, denen Sie begegnen werden, und bietet praktische Lösungen.

Sie erleben wahrscheinlich eine oder mehrere dieser Situationen:

  1. “Ups, ich habe auf main committed, anstatt einen Feature-Branch zu erstellen!”
  2. “Ich habe einen Tippfehler in meiner Commit-Nachricht - kann ich das korrigieren?”
  3. “Mein Feature-Branch ist veraltet - main ist vorangeschritten!”
  4. “Git sagt, meine Branches haben sich auseinanderentwickelt - was soll ich tun?”
  5. “Ich habe Merge-Konflikte - wie löse ich sie?”

Diese Vorlesung behandelt drei kritische Git-Workflows, die Ihnen helfen werden:

Lassen Sie uns diese Herausforderungen in Lernchancen verwandeln!


Teil 1: “Ups, ich habe auf Main committed!” beheben

1.1 Das Problem

Sie haben an einem neuen Feature gearbeitet und mehrere Commits gemacht. Alles scheint in Ordnung zu sein, bis Sie merken: Sie haben direkt auf main committed, anstatt zuerst einen Feature-Branch zu erstellen!

Noch schlimmer - Sie haben bereits zum Remote-Repository gepusht, sodass andere Leute Ihre Commits möglicherweise gesehen haben.

main branch:
A---B---C---D---E---F  (Commits D, E, F sollten auf einem Feature-Branch sein!)

Dies ist ein häufiger Fehler, besonders wenn Sie sich auf den Code konzentrieren und vergessen, zuerst einen Branch zu erstellen.

1.2 Warum das wichtig ist

Best Practice: Feature Branch Workflow

In der professionellen Entwicklung sollten Sie niemals direkt auf main (oder master) committen. Stattdessen:

  1. Erstellen Sie einen Feature-Branch
  2. Machen Sie Ihre Commits dort
  3. Erstellen Sie einen Pull Request (PR) / Merge Request (MR)
  4. Holen Sie Code-Review ein
  5. Mergen Sie nach Genehmigung zu main

Vorteile:

1.3 Die Lösung: Commits zu einem Feature-Branch verschieben

Lassen Sie uns diese Situation Schritt für Schritt beheben. Wir werden die Commits von main zu einem neuen Feature-Branch verschieben.

Szenario: Sie haben 3 Commits (D, E, F), die auf einem Feature-Branch namens feature/my-awesome-feature sein sollten:

Aktueller Zustand:
main: A---B---C---D---E---F (D, E, F sind der Fehler)

Gewünschter Zustand:
main:                   A---B---C
                             \
feature/my-awesome-feature:   D---E---F

Schritt-für-Schritt-Lösung

Schritt 1: Erstellen Sie den Feature-Branch (bewahrt die Commits)

git branch feature/my-awesome-feature

Dies erstellt einen neuen Branch, der auf Ihren aktuellen HEAD (Commit F) zeigt, wechselt aber noch nicht zu ihm.

Wichtig: Dies entfernt nichts - es erstellt nur einen Zeiger auf den aktuellen Zustand.

Schritt 2: Verschieben Sie main zurück vor Ihre Commits

git reset --hard C_COMMIT_HASH

Ersetzen Sie C_COMMIT_HASH durch den Hash des letzten guten Commits (dem vor Beginn Ihrer Feature-Arbeit).

Was git reset --hard tut:

Wie man den richtigen Commit-Hash findet:

git log --oneline -10

Suchen Sie nach dem Commit direkt vor Beginn Ihrer Feature-Arbeit.

Schritt 3: Wechseln Sie zum Feature-Branch

git checkout feature/my-awesome-feature

Schritt 4: Pushen Sie den Feature-Branch zum Remote

git push origin feature/my-awesome-feature

Dies lädt Ihren Feature-Branch mit allen Commits zum Remote-Repository hoch.

Schritt 5: Force pushen Sie main zum Remote (falls Sie bereits gepusht haben)

git push --force-with-lease origin main

⚠️ Warnung: --force-with-lease überschreibt die Remote-Historie. Nutzen Sie dies nur, wenn Sie sicher sind!

Warum Force Push nötig ist: Ihr lokaler main ist jetzt “hinter” dem Remote main (Sie haben Commits entfernt). Git lässt Sie nicht normal pushen, weil Commits verloren gehen würden. Da wir genau das wollen, benötigen wir --force-with-lease.

Vollständige Befehlssequenz

# 1. Erstellen Sie Feature-Branch an aktueller Position
git branch feature/my-awesome-feature

# 2. Verschieben Sie main zurück (ersetzen Sie abc123 durch den korrekten Hash)
git reset --hard abc123

# 3. Wechseln Sie zum Feature-Branch
git checkout feature/my-awesome-feature

# 4. Pushen Sie den Feature-Branch
git push origin feature/my-awesome-feature

# 5. Force pushen Sie main (nur falls Sie bereits zum Remote gepusht haben)
git push --force-with-lease origin main

1.4 Praxisbeispiel: Road Profile Viewer Aufgabe

Die Situation:

Sie sind begeistert, mit der Refactoring-Aufgabe zu beginnen. Sie haben gerade die Anforderungen gelesen - Sie müssen das Geometrie-Modul mit den Ray-Intersection-Funktionen aus der monolithischen main.py-Datei extrahieren.

Sie erstellen die neue road_profile_viewer/geometry.py-Datei, extrahieren die Funktionen find_intersection() und project_point_to_line() und machen Ihren ersten Commit. Aber dann…

# Sie dachten, Sie wären auf einem Feature-Branch, aber...
git status
# On branch main
# Your branch is ahead of 'origin/main' by 1 commit.
#
#   (use "git push" to publish your local commits)

# Oh nein! Die Aufgabe verlangt einen Branch namens 'feature/refactor-to-modules'!
# Sie haben direkt auf main committed!

Warum das ein Problem ist:

Die Wiederherstellung:

# 1. Prüfen Sie die Situation
git log --oneline -3
# a7f3e21 Extract geometry module with intersection functions
# 8b5c742 Initial commit: monolithic road profile viewer
# c4d9a31 Add README and assignment instructions

# 2. Erstellen Sie den erforderlichen Feature-Branch an aktueller Position (behält Ihren Commit)
git branch feature/refactor-to-modules

# 3. Setzen Sie main zurück, um origin/main zu entsprechen (entfernt Commit von main)
git reset --hard origin/main
# HEAD is now at 8b5c742 Initial commit: monolithic road profile viewer

# 4. Wechseln Sie zum Feature-Branch (Ihr Commit ist hier sicher!)
git checkout feature/refactor-to-modules

# 5. Verifizieren Sie, dass Ihr Commit jetzt auf dem Feature-Branch ist
git log --oneline -3
# a7f3e21 Extract geometry module with intersection functions
# 8b5c742 Initial commit: monolithic road profile viewer
# c4d9a31 Add README and assignment instructions

git status
# On branch feature/refactor-to-modules
# nothing to commit, working tree clean

# 6. Pushen Sie den Feature-Branch und fahren Sie mit der Aufgabe fort
git push -u origin feature/refactor-to-modules

Visuelle Darstellung:

Anfangszustand (SCHLECHT):
    origin/main: Initial commit---Monolithic viewer
    local main:  Initial commit---Monolithic viewer---Extract geometry ❌
                                                      ↑
                                                  Sie sind hier
                                             (Falscher Branch!)

Nach Wiederherstellung (GUT):
    origin/main:              Initial commit---Monolithic viewer
    local main:               Initial commit---Monolithic viewer
    feature/refactor-to-modules: Initial commit---Monolithic viewer---Extract geometry ✅
                                                                       ↑
                                                                   Sie sind hier
                                                            (Korrekter Branch!)

Was Sie als Nächstes tun können:

Jetzt können Sie mit dem Aufgaben-Workflow fortfahren:

  1. Fahren Sie mit dem Refactoring fort (extrahieren Sie road.py, visualization.py)
  2. Machen Sie inkrementelle Commits auf Ihrem Feature-Branch
  3. Pushen Sie zum Remote: git push origin feature/refactor-to-modules
  4. Erstellen Sie einen Pull Request auf GitHub
  5. CI-Checks laufen automatisch
  6. Fordern Sie Peer-Review an
  7. Mergen Sie nach Genehmigung

1.5 Warum das funktioniert

  1. git branch feature/my-feature
    • Erstellt einen neuen Branch an Ihrer aktuellen Position
    • Der Commit wird jetzt von main und dem Feature-Branch referenziert
    • Wechselt NICHT die Branches (Sie sind noch auf main)
  2. git reset --hard origin/main
    • Verschiebt den main-Branch-Zeiger zurück, um origin/main zu entsprechen
    • Das --hard-Flag setzt auch Ihr Arbeitsverzeichnis zurück
    • Ihr Commit ist nicht mehr auf main…
    • Aber er ist noch sicher! Der Feature-Branch zeigt noch darauf
  3. git checkout feature/my-feature
    • Wechselt zum Feature-Branch
    • Ihr Commit ist jetzt auf dem korrekten Branch
    • Sie können mit dem normalen PR-Workflow fortfahren

Kerngedanke: Gits Branch-Zeiger sind nur Referenzen zu Commits. Indem Sie einen neuen Branch erstellen, bevor Sie main zurücksetzen, stellen Sie sicher, dass der Commit zugänglich bleibt. Commits gehören nicht zu Branches - Branches zeigen auf Commits!

1.6 Prävention: Wie man das vermeidet

Prüfen Sie Ihren aktuellen Branch

git branch
# * main  ← Warnsignal!

# Oder nutzen Sie git status
git status
# On branch main  ← Warnung!

Erstellen Sie IMMER Ihren Feature-Branch VOR Beginn der Arbeit

# Starten Sie neue Feature-Arbeit
git checkout -b feature/my-awesome-feature

Das -b-Flag erstellt den Branch und wechselt zu ihm in einem Befehl.

Konfigurieren Sie Ihren Shell-Prompt

Viele Shell-Prompts können Ihren aktuellen Git-Branch anzeigen. Dies gibt Ihnen eine konstante visuelle Erinnerung.

Beispiel (oh-my-zsh, bash-git-prompt, etc.):

user@computer ~/project (main) $        # Auf main - Vorsicht!
user@computer ~/project (feature/xyz) $ # Auf Feature-Branch - sicher!

Nutzen Sie Branch-Protection-Regeln

Auf GitHub/GitLab/Bitbucket aktivieren Sie Branch-Protection für main:

Dies verhindert von vornherein versehentliche Commits auf main.


Teil 2: git commit –amend und Rebase-Strategie verstehen

2.1 Das Szenario: Was passiert, wenn Sie amenden

Das Problem, das wir oft erleben:

  1. Anfangszustand: Wir haben Änderungen an Dateien gemacht und sie mit einer beschreibenden Nachricht committed
  2. Der Commit: Erfolgreich Commit zum Remote-Branch gepusht
  3. Kleine Änderung nötig: Eine kleine Bearbeitung gemacht (Tippfehler oder kleine Formatierung korrigiert)
  4. Der Amend: Anstatt einen neuen Commit zu erstellen, haben wir git commit --amend genutzt, um den vorherigen Commit zu modifizieren
  5. Neuer Commit erstellt: Git hat einen neuen Commit mit derselben Nachricht aber anderem Inhalt erstellt
  6. Push fehlgeschlagen: Beim Versuch zu pushen, lehnte Git ab mit der Nachricht:
    Your branch and 'origin/feature/branch-name' have diverged,
    and have 1 and 1 different commits each, respectively.
    

2.2 Warum das passiert ist

Die kritische Erkenntnis: git commit --amend modifiziert keinen existierenden Commit - es erstellt einen völlig neuen Commit.

Vor amend:
    A---B---C (12d3002) ← HEAD, origin/feature/branch

Nach amend:
    A---B---C (12d3002) ← origin/feature/branch
         \
          C' (71db7cf) ← HEAD (lokal)

Die Commits haben:

2.3 Was –amend tut

git commit --amend erlaubt es Ihnen, den letzten Commit zu modifizieren, indem es:

Die technische Realität

Wenn Sie amenden:

git add file.txt
git commit --amend

Git tatsächlich:

  1. Nimmt den aktuellen Staging-Bereich
  2. Nimmt den Tree vom vorherigen Commit
  3. Kombiniert sie zu einem neuen Commit-Objekt
  4. Aktualisiert HEAD, um auf diesen neuen Commit zu zeigen
  5. Der alte Commit wird “dangling” (existiert noch, aber nicht referenziert)

2.4 Warum es mächtig ist

Beispiel: Unordentliche Historie (ohne –amend)

* fix typo in README
* oops forgot to add file
* actually add the feature
* fix formatting in feature
* Feature: Add user authentication

Saubere Historie (mit –amend)

* Feature: Add user authentication

All diese Zwischen-“Oops”-Commits werden zu einer logischen Einheit kombiniert.

2.5 Die Rebase-Strategie und –amend

In modernen Git-Workflows (besonders in professionellen Umgebungen) nutzen Teams oft:

Ziel: Die Projekthistorie als saubere, lineare Geschichte von Änderungen halten.

Merge-Strategie (erstellt Merge-Commits):
    A---B---C (main)
         \   \
          D---E---M (Feature gemergt)

Rebase-Strategie (lineare Historie):
    A---B---C---D'---E' (main mit Feature)

Wie –amend hineinpasst

Bevor Sie zum Remote pushen, können Sie Ihre lokale Historie frei umschreiben:

  1. Machen Sie einen Commit:
    git commit -m "Add feature X"
    
  2. Merken Sie, dass Sie etwas vergessen haben:
    git add forgotten_file.js
    git commit --amend --no-edit
    
  3. Korrigieren Sie einen Tippfehler in der Commit-Nachricht:
    git commit --amend -m "Add feature X with proper error handling"
    

Ergebnis: Ein sauberer Commit anstatt mehrerer “Fix”-Commits.

2.6 Die goldene Regel: Wann Umschreiben der Historie gefährlich ist

⚠️ Kritische Warnung

Schreiben Sie niemals Commits um, die zu einem geteilten Branch gepusht wurden, an dem andere arbeiten!

Sicher zu amenden/rebasen:

Lokale Commits (noch nicht gepusht) ✅ Feature-Branches, wo Sie der einzige Entwickler sind ✅ Nach Force-Push zu Ihrem eigenen Feature-Branch (was wir getan haben)

Gefährlich zu amenden/rebasen:

Main/Master-Branch mit Teammitgliedern ❌ Geteilte Feature-Branches mit mehreren Entwicklern ❌ Öffentliche Releases oder Tags

Warum es gefährlich ist

Wenn jemand seine Arbeit auf Commit 12d3002 basiert hat und Sie 71db7cf force pushen:

Ihre Situation:
    A---B---C (12d3002, ihre Arbeit basiert hier)
             \
              D---E (ihre neuen Commits)

Nach Ihrem Force-Push:
    A---B---C' (71db7cf, anderer Commit!)

    Ihre Commits D und E sind jetzt verwaist!

2.7 Die Lösung: Force Push (mit Vorsicht)

Nach dem Amenden haben sich die lokale und Remote-Historie auseinanderentwickelt. Um das Remote zu aktualisieren:

git push --force-with-lease

–force-with-lease vs –force

--force-with-lease (sicherer):

--force (gefährlich):

Was in unserem Fall passiert ist

# Vor Force-Push
Lokal:  A---B---C' (71db7cf) ← HEAD
Remote: A---B---C (12d3002) ← origin/feature/branch

# Nach Force-Push
Lokal:  A---B---C' (71db7cf) ← HEAD
Remote: A---B---C' (71db7cf) ← origin/feature/branch

# Der alte Commit 12d3002 ist jetzt auf Remote nicht referenziert

2.8 Best Practices

Amenden Sie früh, amenden Sie oft (lokal)

Während der Arbeit an einem Feature:

# Anfangsarbeit
git add .
git commit -m "WIP: Add feature"

# Mehr Arbeit hinzufügen
git add .
git commit --amend --no-edit

# Weiter verfeinern vor dem Push
git add .
git commit --amend

Ergebnis: Ein polierter Commit, wenn Sie schließlich pushen.

Nutzen Sie beschreibende Branch-Namen

feature/user-authentication
bugfix/login-timeout
refactor/database-layer

Dies macht klar, dass der Branch:

Kommunizieren Sie Force-Pushes

Falls andere Ihren Branch beobachten könnten:

# Slack/Discord-Nachricht
"⚠️ Force-Push zu feature/branch-name
Bitte pullen Sie mit --rebase, falls Sie lokale Änderungen haben!"

Die Pre-Push-Checkliste

Vor git push --force-with-lease:

2.9 Interaktives Rebase: Das Power-Tool

--amend funktioniert nur beim letzten Commit. Für ältere Commits nutzen Sie interaktives Rebase:

git rebase -i HEAD~3  # Bearbeitet die letzten 3 Commits

Sie können:

Beispiel:

# Ihre unordentliche Historie
git log --oneline
a1b2c3d Fix typo
b2c3d4e Add feature part 3
c3d4e5f Fix bug in part 2
d4e5f6g Add feature part 2
e5f6g7h Add feature part 1

# Starten Sie interaktives Rebase
git rebase -i HEAD~5

# Editor öffnet sich mit:
pick e5f6g7h Add feature part 1
pick d4e5f6g Add feature part 2
pick c3d4e5f Fix bug in part 2
pick b2c3d4e Add feature part 3
pick a1b2c3d Fix typo

# Ändern Sie zu:
pick e5f6g7h Add feature part 1
squash d4e5f6g Add feature part 2
fixup c3d4e5f Fix bug in part 2
squash b2c3d4e Add feature part 3
fixup a1b2c3d Fix typo

# Ergebnis: Ein sauberer Commit
git log --oneline
f7g8h9i Add complete user profile feature

2.10 Kurzreferenz

Amended den letzten Commit

git commit --amend                    # Bearbeitet Nachricht und fügt gestaged Änderungen hinzu
git commit --amend --no-edit          # Fügt nur gestaged Änderungen hinzu
git commit --amend -m "Neue Nachricht"   # Ändert nur Nachricht

Force pusht sicher

git push --force-with-lease           # Sicherer Force Push
git push --force                      # Gefährlicher Force Push

Interaktives Rebase

git rebase -i HEAD~3                  # Bearbeitet letzte 3 Commits
git rebase -i main                    # Rebaset ganzen Branch auf main

Macht Amend rückgängig (Notfall!)

git reflog                            # Findet vorherigen Commit
git reset --soft HEAD@{1}             # Macht Amend rückgängig, behält Änderungen gestaged

Teil 3: Git Rebase vs Merge - Workflow-Strategien und Konfliktmanagement

3.1 Das häufige Szenario

Sie arbeiten an einem Feature-Branch, aber main steht nicht still:

Tag 1: Feature-Branch erstellen
main:    A---B---C
              \
feature:       D

Tag 3: Kollegen mergen ihre Arbeit
main:    A---B---C---E---F---G  (vorangeschritten!)
              \
feature:       D---H---I         (Ihre Arbeit geht weiter)

Frage: Wie bleiben Sie mit main synchronisiert?

Die Herausforderung:

3.2 Warum synchronisiert bleiben wichtig ist

Problem 1: Konflikte wachsen mit der Zeit

Woche 1: Main hat 2 neue Commits
- Kleine Konflikte, leicht zu lösen

Woche 2: Main hat 10 neue Commits
- Große Konflikte, schwer zu lösen
- Sie haben den Kontext Ihres alten Codes vergessen

Problem 2: Integrationsprobleme werden spät entdeckt

Ihr Branch:
- Funktioniert perfekt isoliert
- Alle Tests bestehen

Main-Branch:
- API vor 3 Tagen geändert
- Ihr Code jetzt inkompatibel

Wenn Sie bis zur PR-Zeit warten:
- Große Überraschung! Nichts funktioniert
- Dauert Tage zu reparieren
- Blockiert andere Arbeit

Problem 3: Schwierige Code-Review

PR mit veraltetem Branch:
Reviewer: "Moment, das konfligiert mit der neuen API"
Sie: "Lassen Sie mich rebasen..."
Reviewer: "Das Diff hat sich geändert, ich muss nochmal reviewen"

PR mit aktuellem Branch:
Reviewer: "Sieht gut aus, funktioniert bereits mit neuestem main"
Schnelle Genehmigung!

Die goldene Regel

“Ein main merge/rebase am Tag hält die Konflikte fern!”

Warum das funktioniert:

3.3 Die zwei Strategien

Strategie 1: Main in Feature mergen (Merge-Strategie)

Der Workflow:

# Tägliche Routine (auf Feature-Branch)
git fetch --prune
git merge origin/main
# Lösen Sie Konflikte falls vorhanden
git push

Was passiert:

Vor Merge:
main:    A---B---C---E---F---G
              \
feature:       D---H---I

Nach git merge origin/main:
main:    A---B---C---E---F---G
              \             \
feature:       D---H---I---M  (M = Merge-Commit)

Visuelle Erklärung:

Vorteile:

✅ Einfaches mentales Modell (kombiniert einfach Branches)
✅ Bewahrt exakte Historie (zeigt wann Integration stattfand)
✅ Jeder Konflikt nur einmal gelöst (im Merge-Commit)
✅ Kein Force Push nötig (sicher!)
✅ Sicher, wenn mehrere Leute am selben Branch arbeiten
✅ Kann leicht rückgängig gemacht werden (git reset vor Merge)

Nachteile:

❌ Erstellt Merge-Commits (verstopft Historie)
❌ Nicht-lineare Historie (schwerer git log zu lesen)
❌ PR-Diff könnte unzusammenhängende Änderungen von main enthalten
❌ "Unordentlich" aussehender Git-Graph

Strategie 2: Feature auf Main rebasen (Rebase-Strategie)

Der Workflow:

# Tägliche Routine (auf Feature-Branch)
git fetch --prune
git rebase origin/main
# Lösen Sie Konflikte falls vorhanden
git push --force-with-lease

Was passiert:

Vor Rebase:
main:    A---B---C---E---F---G
              \
feature:       D---H---I

Nach git rebase origin/main:
main:    A---B---C---E---F---G
                           \
feature:                    D'---H'---I'  (Commits umgeschrieben!)

Visuelle Erklärung:

Vorteile:

✅ Saubere, lineare Historie
✅ Keine Merge-Commits, die das Log verstopfen
✅ Einfacher zu lesendes Git Log (gerade Linie)
✅ PR-Review zeigt nur Ihre Änderungen
✅ Einfacher bestimmte Commits zu cherry-picken oder zu reverten
✅ Professionell aussehende Historie

Nachteile:

❌ Schreibt Historie um (ändert Commit-Hashes)
❌ Verlangt Force Push (gefährlich wenn nicht vorsichtig!)
❌ Konflikte könnten mehrmals erscheinen (pro Commit)
❌ Verliert Information darüber, wann Integration stattfand
❌ Komplexer zu verstehen (für Anfänger)
❌ Gefährlich wenn andere am selben Branch arbeiten

3.4 Konflikte - Wann und Wie

Wie Konflikte entstehen

Ein Konflikt tritt auf, wenn:

  1. Dieselbe Datei in beiden Branches modifiziert wurde
  2. Dieselben Zeilen (oder benachbarte Zeilen) unterschiedlich geändert wurden
  3. Git nicht automatisch entscheiden kann, welche Änderung zu behalten ist

Beispiel-Konflikt:

Szenario:
- Sie haben Zeile 10 in main.py geändert
- Kollege hat Zeile 10 in main.py anders geändert
- Beide Änderungen basieren auf alter Version

Wenn Sie mergen/rebasen:
Git sagt: "Ich weiß nicht, welche Zeile 10 korrekt ist!"

Merge-Strategie-Konflikte

Wie Konflikte erscheinen:

$ git merge origin/main
Auto-merging main.py
CONFLICT (content): Merge conflict in main.py
Automatic merge failed; fix conflicts and then commit the result.

Wie der Konflikt aussieht:

# main.py
def calculate_total(items):
<<<<<<< HEAD  (Ihr Branch)
    return sum(item.price * item.quantity for item in items)
=======  (main Branch)
    return sum(item.final_price() * item.quantity for item in items)
>>>>>>> origin/main

Den Konflikt lösen:

# 1. Öffnen Sie main.py, bearbeiten Sie um Konflikt zu lösen
# Wählen Sie eine Version oder kombinieren Sie sie:
def calculate_total(items):
    return sum(item.final_price() * item.quantity for item in items)

# 2. Markieren Sie als gelöst
git add main.py

# 3. Schließen Sie den Merge ab
git commit  # Git füllt automatisch Merge-Commit-Nachricht

Kernpunkt: Sie lösen den Konflikt einmal im Merge-Commit, und fertig!

Rebase-Strategie-Konflikte

Wie Konflikte erscheinen:

$ git rebase origin/main
Applying: Add feature X
CONFLICT (content): Merge conflict in main.py
error: could not apply 7ea41f8... Add feature X
Resolve all conflicts manually, mark them as resolved with
"git add/rm <conflicted_files>", then run "git rebase --continue".

Der Unterschied: Rebase wendet Commits einen nach dem anderen an.

Wenn Sie 3 Commits haben (D, H, I):

Schritt 1: Wendet D auf G an
- Könnte konfligieren → lösen → fortfahren

Schritt 2: Wendet H auf (G + D') an
- Könnte konfligieren → lösen → fortfahren

Schritt 3: Wendet I auf (G + D' + H') an
- Könnte konfligieren → lösen → fortfahren

Das Problem: Derselbe Konflikt mehrmals!

Commit D: Zeile 10 in main.py geändert
Commit H: Zeile 10 in main.py erneut geändert
Commit I: Zeile 10 in main.py erneut geändert

Main hat auch Zeile 10 geändert.

Ergebnis:
- Konflikt beim Anwenden von D → lösen
- Konflikt beim Anwenden von H → lösen (derselbe Bereich!)
- Konflikt beim Anwenden von I → lösen (derselbe Bereich wieder!)

Rebase-Konflikte lösen:

# Für jeden Commit, der konfligiert:

# 1. Öffnen Sie main.py, lösen Sie Konflikt
vim main.py

# 2. Markieren Sie als gelöst
git add main.py

# 3. Fahren Sie mit Rebase fort
git rebase --continue

# Wiederholen Sie für jeden konfligierenden Commit!

Notausgänge:

# Wenn Konflikte zu komplex:
git rebase --abort  # Beginnt von vorne, Branch unverändert

# Wenn ein Commit übersprungen werden soll:
git rebase --skip  # Gefährlich! Nur wenn Commit redundant ist

Konfliktlösung vergleichen

Aspekt Merge Rebase
Häufigkeit Einmal (im Merge-Commit) Pro konfligierendem Commit
Komplexität Alles auf einmal lösen Inkrementell lösen
Derselbe Konflikt Einmal gelöst Könnte mehrmals erscheinen
Kontext Sieht Änderungen beider Branches Sieht Commit für Commit
Abbrechen git merge --abort git rebase --abort
Nach Lösung git commit git rebase --continue

Was ist einfacher?

Bei kleinen Konflikten: Rebase kann einfacher sein (inkrementell)

Beispiel: 3 Commits, jeder mit winzigem Konflikt
Rebase: 3 kleine Konflikte nacheinander lösen
Merge: 1 mittleren Konflikt auf einmal lösen

Gewinner: Rebase (mundgerechte Häppchen)

Bei großen Konflikten: Merge ist normalerweise einfacher

Beispiel: 10 Commits, dieselbe Datei in jedem berührt
Rebase: DENSELBEN Konflikt 10 Mal lösen!
Merge: Konflikt EINMAL lösen

Gewinner: Merge (keine Wiederholung)

Der Schlüsselfaktor: Tägliche Updates!

Mit täglichen Updates:

Ohne tägliche Updates:

3.5 Praktische Workflow-Beispiele

Beispiel 1: Solo-Entwickler (Rebase empfohlen)

Situation:

Täglicher Workflow:

# Morgen: Start des Arbeitstags
git checkout feature/my-feature
git fetch --prune
git rebase origin/main
# Lösen Sie etwaige Konflikte
git push --force-with-lease

# Während des Tags: Reguläre Commits
git add .
git commit -m "Progress on feature"
git push

# Abend: Prüfen Sie ob main sich bewegt hat
git fetch --prune
# Falls main aktualisiert, erneut rebasen
git rebase origin/main
git push --force-with-lease

Vorteile:

Beispiel 2: Team-Feature-Branch (Merge empfohlen)

Situation:

Täglicher Workflow:

# Morgen: Start des Arbeitstags
git checkout feature/team-feature
git pull  # Holt Arbeit der Teammitglieder
git fetch --prune
git merge origin/main
# Lösen Sie etwaige Konflikte
git push

# Während des Tags: Reguläre Commits
git add .
git commit -m "My part of feature"
git push

# Vor Tagesende: Erneut synchronisieren
git pull  # Holt Nachmittagsarbeit der Teammitglieder

Vorteile:

Beispiel 3: Langläufiges Feature (Hybrid-Ansatz)

Situation:

Strategie: Merge während Entwicklung, Rebase vor PR

# Während Entwicklung (täglich):
git merge origin/main  # Sicher, kein Force Push
# Arbeit geht weiter...

# Vor PR-Erstellung (finale Aufräumung):
git rebase -i origin/main  # Interaktives Rebase
# Squasht Commits, räumt Historie auf
git push --force-with-lease

# Erstellt PR mit sauberer Historie

Vorteile:

3.6 Entscheidungsmatrix

Wann Rebase nutzen

Nutzen Sie Rebase wenn:

  1. Allein arbeiten am Feature-Branch
    • Niemand sonst von Historien-Umschreibung betroffen
    • Force Push ist sicher
  2. Kurzlebiger Branch (< 1-2 Wochen)
    • Begrenzte Gelegenheit für Konflikte
    • Rebase handhabbar
  3. Saubere Historie wollen für PR-Review
    • Lineare Historie einfacher zu reviewen
    • Zeigt logische Progression der Arbeit
  4. Häufig aktualisieren (täglich oder öfter)
    • Konflikte bleiben klein
    • Schreibt wenige Commits jedes Mal um
  5. Feature noch nicht gepusht wurde
    • Keine Remote-Historie, um die man sich sorgen muss
    • Kann frei umschreiben

Beispiel-Befehl:

git rebase origin/main
git push --force-with-lease

Wann Merge nutzen

Nutzen Sie Merge wenn:

  1. Mehrere Leute am Branch arbeiten
    • Force Push würde ihre Arbeit brechen
    • Geteilte Historie muss bewahrt werden
  2. Langläufiger Branch (> 2 Wochen)
    • Viele Commits angesammelt
    • Rebase wäre schmerzhaft
  3. Nicht force pushen wollen
    • Sicherer, konservativerer Ansatz
    • Weniger Fehlerrisiko
  4. Exakte Historie bewahren wollen
    • Sehen wann Integrationen stattfanden
    • Entwicklungszeitlinie verstehen
  5. Große, komplexe Konflikte erwartet
    • Einmal lösen vs. mehrmals
    • Weniger repetitive Konfliktlösung

Beispiel-Befehl:

git merge origin/main
git push  # Kein Force nötig!

Entscheidungsflussdiagramm

START: Muss Feature-Branch mit neuestem main aktualisieren
  ↓
Arbeite allein an diesem Branch?
  ├─ Ja → Branch kurzlebig (< 2 Wochen)?
  │         ├─ Ja → Komfortabel mit Rebase?
  │         │         ├─ Ja → NUTZE REBASE ✅
  │         │         └─ Nein  → NUTZE MERGE ✅
  │         └─ Nein  → NUTZE MERGE ✅
  └─ Nein  → NUTZE MERGE ✅

Zusammenfassung:
- Standard ist MERGE (sicherer)
- Nutzt REBASE nur wenn:
  * Solo-Entwickler
  * Kurzer Branch
  * Komfortabel mit Force Push

3.7 Best Practices für täglichen Workflow

Das tägliche Sync-Ritual

Wählen Sie einen und halten Sie sich daran:

Option A: Rebase (saubere Historie):

# Jeden Morgen
git checkout feature/my-feature
git fetch --prune
git rebase origin/main
git push --force-with-lease

Option B: Merge (sicher):

# Jeden Morgen
git checkout feature/my-feature
git fetch --prune
git merge origin/main
git push

Warum täglich?

Nutzen Sie --force-with-lease nicht --force

Schlecht:

git push --force  # Überschreibt Remote blind

Gut:

git push --force-with-lease  # Prüft ob Remote sich nicht geändert hat

Warum --force-with-lease sicherer ist:

Szenario:
1. Sie rebasen lokal
2. Teammitglied pusht zum selben Branch (Sie wissen es nicht!)
3. Sie force pushen

--force:
→ Arbeit des Teammitglieds VERLOREN! 💥

--force-with-lease:
→ Push abgelehnt! Git sagt "Remote hat sich geändert seit letztem Fetch"
→ Sie fetchen, sehen Arbeit des Teammitglieds, koordinieren
→ Kein Datenverlust ✅

Kommunizieren Sie mit Ihrem Team

Beim Rebasen eines geteilten Branches:

# Im Team-Chat:
"Hey Team, ich werde gleich feature/team-feature auf neuesten main rebasen.
Bitte pushen Sie jetzt alle ausstehenden Arbeiten, dann re-clonen Sie nach meinem Abschluss."

# Warten Sie auf Antworten...

# Dann rebasen
git rebase origin/main
git push --force-with-lease

# Benachrichtigen Sie Team:
"Rebase fertig! Bitte führen Sie aus: git fetch && git reset --hard origin/feature/team-feature"

Beim Mergen (keine Kommunikation nötig):

git merge origin/main
git push  # Team kann jederzeit pullen, keine Störung

Lösen Sie Konflikte sorgfältig

Während Merge:

# 1. Sehen Sie welche Dateien konfligieren
git status

# 2. Öffnen Sie jede Datei, suchen Sie nach:
<<<<<<< HEAD
Ihr Code
=======
deren Code
>>>>>>> origin/main

# 3. Wählen Sie korrekte Version oder kombinieren Sie

# 4. Testen Sie! Stellen Sie sicher, es funktioniert
npm test  # oder was auch immer Ihr Test-Befehl ist

# 5. Markieren Sie als gelöst und committen Sie
git add .
git commit

Während Rebase:

# Derselbe Prozess, aber nach jedem Commit:
git add .
git rebase --continue

# Wiederholen Sie bis fertig

Goldene Regel: Testen Sie immer nach Konfliktlösung!

Kennen Sie Ihre Notausgänge

Merge rückgängig machen:

git merge --abort  # Vor Commit
git reset --hard HEAD~1  # Nach Commit (letzter Commit)

Rebase rückgängig machen:

git rebase --abort  # Während Rebase

# Nach abgeschlossenem Rebase:
git reflog  # Findet Commit vor Rebase
git reset --hard HEAD@{5}  # Oder welchen Reflog-Eintrag auch immer

Force Push rückgängig machen:

# Findet alten Commit
git reflog
# oder auf GitHub: Prüft Branch-Historie vor Force Push

# Force pusht zurück zum alten Zustand
git reset --hard <alter-commit-sha>
git push --force-with-lease

3.8 Häufige Fallstricke und Lösungen

Fallstrick 1: Zu lange warten mit Synchronisierung

Problem:

Woche 1: Branch von Commit C erstellt
Woche 2: Main ist bei Commit G (4 Commits voraus)
Woche 3: Main ist bei Commit M (10 Commits voraus)
Woche 4: Main ist bei Commit Z (20 Commits voraus)

Zeit zum PR-Merge:
- Massive Konflikte
- Tage zum Lösen
- Alles kaputt
- Neu anfangen? 😢

Lösung:

# Tägliche Synchronisierung (wählen Sie einen):
git merge origin/main  # oder
git rebase origin/main

# Dauert 5 Minuten pro Tag vs. Tage am Ende

Fallstrick 2: Force Push zu geteiltem Branch

Problem:

Entwickler A:
feature: A---B---C---D---E

Entwickler B:
feature: A---B---C---D---E---F (gepusht)

Entwickler A rebaset:
feature: A---B---C'---D'---E' (force push)

Entwickler B:
→ Git sagt "diverged"
→ Ihre Arbeit (F) ist verwaist!
→ 😢

Lösung:

# Wenn mehrere Leute: NICHT REBASEN!
git merge origin/main  # Sicher für geteilte Branches

Fallstrick 3: Vergessen nach Konfliktlösung zu testen

Problem:

Konflikt lösen:
- "Ihre" Version wählen
- git add, git commit
- Push

Später:
- Build kaputt
- Tests schlagen fehl
- Ups! 😬

Lösung:

# Nach Konfliktlösung:
git add .

# VOR Commit:
npm test  # oder pytest, oder was auch immer
npm run build

# Nur wenn Tests bestehen:
git commit

Fallstrick 4: Arbeit verlieren mit git reset --hard

Problem:

git reset --hard origin/main  # Ups! Arbeit verloren!

Lösung:

# Falls gerade gemacht:
git reflog  # Findet verlorene Commits
git reset --hard HEAD@{3}  # Stellt wieder her

# Prävention: Prüfen Sie was Sie verlieren werden
git log HEAD..origin/main  # "Was werde ich verlieren?"
git diff HEAD origin/main   # "Welche Änderungen werde ich verlieren?"

Fallstrick 5: Rebase-Konflikt-Ermüdung

Problem:

git rebase origin/main
→ Konflikt in Commit D... lösen, fortfahren
→ Konflikt in Commit E... lösen, fortfahren
→ Konflikt in Commit F... lösen, fortfahren
→ Konflikt in Commit G... lösen, fortfahren
→ "Ich gebe auf!" 😩

Lösung:

# Brechen Sie Rebase ab
git rebase --abort

# Nutzen Sie stattdessen Merge
git merge origin/main  # Einmal lösen, fertig!

# Oder: Interaktives Rebase um Commits zuerst zu squashen
git rebase -i HEAD~10  # Kombiniert Commits
git rebase origin/main  # Weniger Commits = weniger Konflikte

Fazit: Zusammenfassung und Empfehlungen

Schnelle Entscheidungshilfe

Stellen Sie sich diese Fragen:

  1. Bin ich der einzige, der an diesem Branch arbeitet?
    • Ja → Erwägen Sie Rebase
    • Nein → Nutzen Sie Merge
  2. Ist dieser Branch kurzlebig (< 2 Wochen)?
    • Ja → Erwägen Sie Rebase
    • Nein → Nutzen Sie Merge
  3. Bin ich komfortabel mit Force Push?
    • Ja → Erwägen Sie Rebase
    • Nein → Nutzen Sie Merge
  4. Will ich saubere, lineare Historie?
    • Ja → Erwägen Sie Rebase
    • Nein (oder egal) → Nutzen Sie Merge

Wenn 3-4 Antworten Rebase favorisieren → Nutzen Sie Rebase Wenn 0-2 Antworten Rebase favorisieren → Nutzen Sie Merge

Anfänger (0-6 Monate mit Git)

Nutzen Sie Merge:

git fetch --prune
git merge origin/main
git push

Warum:

Fortgeschritten (6-24 Monate mit Git)

Nutzen Sie Rebase für Solo-Branches:

git fetch --prune
git rebase origin/main
git push --force-with-lease

Nutzen Sie Merge für Team-Branches:

git fetch --prune
git merge origin/main
git push

Warum:

Experte (24+ Monate mit Git)

Nutzen Sie Hybrid-Ansatz:

# Während Entwicklung:
git merge origin/main  # Sicher, häufige Syncs

# Vor PR:
git rebase -i origin/main  # Räumt Historie auf
git push --force-with-lease

Warum:

Die universelle Regel (alle Levels)

Aktualisieren Sie Ihren Branch täglich (oder mindestens alle 2-3 Tage):

# Wählen Sie einen und machen Sie es TÄGLICH:

# Option A: Merge (sicherer)
git fetch --prune && git merge origin/main

# Option B: Rebase (sauberer)
git fetch --prune && git rebase origin/main

# Der Schlüssel ist: MACHEN SIE ES REGELMÄSSIG!

Warum das wichtiger ist als Rebase vs. Merge:

Wichtigste Erkenntnisse

  1. “Ein main merge/rebase am Tag hält die Konflikte fern”
    • Wichtigste Praxis
    • Funktioniert mit beiden Strategien
    • Verhindert Konfliktanhäufung
  2. Commits stecken nicht auf Branches fest - Branches zeigen auf Commits
    • Branch erstellen vor Reset bewahrt Commits
    • Dies zu verstehen macht Git weniger beängstigend
  3. git commit --amend schreibt Historie um indem es einen neuen Commit erstellt
    • Nutzen Sie es frei bei lokalen Commits
    • Niemals bei geteilten/gepushten Commits (außer Sie wissen was Sie tun)
  4. Merge ist die sicherere Voreinstellung
    • Funktioniert für Teams
    • Kein Force Push nötig
    • Einfacher zu verstehen
    • Kann nicht schiefgehen
  5. Rebase erstellt sauberere Historie
    • Aber verlangt Force Push
    • Nur für Solo-Branches
    • Verlangt mehr Git-Wissen
    • Lohnt sich eventuell zu lernen
  6. Beide Strategien funktionieren gut mit täglichen Updates
    • Konflikte bleiben klein
    • Wählen Sie basierend auf Team/Präferenz
    • Konsistenz zählt mehr als Wahl
  7. Testen Sie nach Konfliktlösung
    • Jedes einzelne Mal
    • Keine Ausnahmen
    • Verhindert kaputte Builds
  8. Nutzen Sie --force-with-lease nicht --force
    • Sicherer Force Push
    • Verhindert Datenverlust
    • Immer bevorzugen
  9. Kommunizieren Sie beim Rebasen geteilter Branches
    • Koordinieren Sie mit Team
    • Minimiert Störung
    • Oder nutzen Sie einfach stattdessen Merge

Befehlsreferenz

Tägliche Sync-Befehle

Merge-Strategie:

git fetch --prune
git merge origin/main
git push

Rebase-Strategie:

git fetch --prune
git rebase origin/main
git push --force-with-lease

Konfliktlösung

Während Merge:

# Sehen Sie Konflikte
git status

# Nach Lösung:
git add <datei>
git commit

Während Rebase:

# Sehen Sie Konflikte
git status

# Nach Lösung:
git add <datei>
git rebase --continue

Notausgänge

Merge abbrechen:

git merge --abort

Rebase abbrechen:

git rebase --abort

Letzten Commit rückgängig machen (nur lokal):

git reset --hard HEAD~1

Aus Reflog wiederherstellen:

git reflog
git reset --hard HEAD@{N}

Sicherer Force Push

Nutzen Sie immer:

git push --force-with-lease

Nutzen Sie niemals (außer Sie wissen genau was Sie tun):

git push --force  # ⚠️ Gefährlich!

Denken Sie daran: Die beste Strategie ist die, auf die sich Ihr Team einigt und die Sie konsistent nutzen. Im Zweifelsfall ist Merge die sicherere Wahl! Mit großer Git-Macht kommt große Verantwortung - nutzen Sie diese Tools weise! 🚀

Zusätzliche Ressourcen

Offizielle Dokumentation

Tutorials und Anleitungen

Best Practices

© 2026 Dominik Mueller   •  Powered by Soopr   •  Theme  Moonwalk