git merge
Zwei oder mehr Entwicklungsverläufe zusammenführen
Der Befehl 'git merge' übernimmt die Änderungen der genannten Commits (seit ihre Historie vom aktuellen Branch abgezweigt ist) in den aktuellen Branch. Git macht wenn möglich einen „Fast-Forward“-Merge (wenn der aktuelle Branch ein Vorfahre des gemergten Branches ist) oder erzeugt einen „Merge-Commit“, wenn die Historien auseinandergelaufen sind. Gibt es Konflikte zwischen den Branches, hält Git an und bittet dich, sie zu lösen, bevor der Merge abgeschlossen wird.
Syntax
git merge [--no-ff | --ff-only] [--squash] [--no-commit] [-m <msg>] [--allow-unrelated-histories] [<commit>...]
git merge (--continue | --abort | --quit)Optionen
Die richtige Option wählen
Merge-Strategien
Wie du steuerst, welche Art Merge Git durchführt
| Befehl | Erzeugt Merge-Commit | Bewahrt Historie | Am besten für |
|---|---|---|---|
git merge (default) | Wenn auseinandergelaufen | Ja | Normale Feature-Integration |
git merge --no-ff | Immer | Ja | Feature-Merges dokumentieren |
git merge --ff-only | Nie | Nur linear | Saubere Historie erzwingen |
git merge --squash | Nein (normaler Commit) | Nein (flachgedrückt) | Sauberer main-Branch |
Konflikte behandeln
Was tun, wenn ein Merge Konflikte hat
| Befehl | Aktion | Behält Arbeit | Wann verwenden |
|---|---|---|---|
(resolve manually) | Dateien bearbeiten, git add | Ja | Teile von beiden Seiten nötig |
--continue | Merge abschließen | Ja | Nach dem Lösen der Konflikte |
--abort | Merge abbrechen | Zustand vor dem Merge | Jetzt nicht bereit zum Lösen |
checkout --ours/--theirs | Eine Seite wählen | Eine Version | Eine Seite ist eindeutig richtig |
merge oder rebase
Zwei Wege, Änderungen zu integrieren – mit unterschiedlichen Vor- und Nachteilen
| Befehl | Historie | Konfliktlösung | Am besten für |
|---|---|---|---|
git merge | Bewahrt alle Commits | Einmal | Geteilte Branches, PRs |
git rebase | Schreibt linear um | Pro Commit | Lokales Aufräumen, private Branches |
git merge --squash | Ein einziger Commit | Einmal | Feature mit unordentlicher Historie |
Den Commit steuern
Optionen zum Anpassen des Merge-Commits
| Befehl | Committet automatisch | Anwendungsfall |
|---|---|---|
git merge feature | Ja (ohne Konflikte) | Normaler Merge |
git merge --no-commit | Nein (gestagt) | Vor dem Commit prüfen |
git merge -m "msg" | Ja (bei Fast-Forward ignoriert) | Aussagekräftige Merge-Commits |
git merge --squash | Nein (Commit nötig) | Alle Commits zu einem zusammenfassen |
Workflow-Beispiele
git checkout mainAuf den Branch main wechseln
git pull origin mainDie neuesten Änderungen vom Remote holen
git merge --no-ff feature-branchDas Feature mit einem Merge-Commit für die Historie mergen
git push origin mainDie gemergten Änderungen zum Remote pushen
git branch -d feature-branchDen gemergten Feature-Branch löschen
git merge featureDen Merge versuchen (es gibt Konflikte)
git statusSehen, welche Dateien Konflikte haben
(edit conflicted files)Nach <<<<<<<-Markern suchen und von Hand lösen
git add <resolved-files>Die gelösten Dateien stagen
git merge --continueDen Merge mit einem Commit abschließen
git checkout mainAuf den Branch main wechseln
git merge --squash feature-branchAlle Commits zu gestagten Änderungen zusammenfassen
git commit -m "Add feature X"Einen sauberen Commit mit allen Änderungen erzeugen
git branch -D feature-branchDen Feature-Branch erzwungen löschen
git merge featureDen Merge starten (es treten Probleme auf)
git statusDen Konfliktzustand ansehen
git merge --abortAbbrechen und den Zustand vor dem Merge wiederherstellen
git statusPrüfen, dass du wieder in einem sauberen Zustand bist
Fehlerbehebung
CONFLICT (content): Merge conflict in file.js
Ursache: Beide Branches haben dieselben Zeilen der Datei geändert
Öffne die Datei, suche die <<<<<<<-Marker, löse den Konflikt, dann git add und git merge --continue
fatal: refusing to merge unrelated histories
Ursache: Die Branches haben keinen gemeinsamen Vorfahren (getrennte Repositories)
Nutze git merge --allow-unrelated-histories, wenn du absichtlich getrennte Projekte zusammenführen willst
Already up to date
Ursache: Der Branch, den du mergst, ist schon in deinem aktuellen Branch enthalten
Nichts zu tun – dein Branch enthält schon alle Commits des Ziels
error: Your local changes to the following files would be overwritten by merge
Ursache: Du hast nicht committete Änderungen, die mit dem Merge kollidieren
Committe deine Änderungen, stashe sie (git stash) oder verwirf sie vor dem Mergen
Merge ist passiert, aber ich wollte vorher prüfen
Ursache: Git hat den Merge automatisch committet
Nutze nächstes Mal --no-ff --no-commit. Zum Wiederholen: git reset --merge ORIG_HEAD, dann erneut mit --no-commit mergen
Tipps & Stolperfallen
Best Practices
- ✓Pulle vor dem Mergen immer die neuesten Änderungen, um Konflikte gering zu halten
- ✓Nutze --no-ff für Feature-Branches, damit der Merge-Kontext in der Historie erhalten bleibt
- ✓Schreibe aussagekräftige Merge-Nachrichten, die erklären, was integriert wurde
- ✓Lösche Feature-Branches nach dem Merge, damit das Repository aufgeräumt bleibt
- ✓Teste deinen Code nach dem Merge und vor dem Push, um sicherzugehen, dass nichts kaputt ist
- ✓Nutze git merge --abort, wenn du noch nicht bereit bist, Konflikte zu lösen – lass keinen halbfertigen Merge liegen
- ✓Merge bei langlebigen Branches regelmäßig main in deinen Feature-Branch, um Konflikte beim finalen Merge zu verringern
Häufige Fehler
- ✗Mergen, ohne vorher die neuesten Änderungen vom Remote zu pullen. Führe vor dem Mergen immer 'git pull' aus, um Konflikte zu vermeiden.
- ✗Dateien stagen, die noch Konfliktmarker enthalten. Git blockiert Commits, solange Pfade ungemergt sind – aber sobald du eine Datei mit 'git add' stagst, committet es die <<<<<<<-Marker unverändert.
- ✗Fast-Forward-Merges für Feature-Branches lassen die Branch-Historie verschwinden. Nutze '--no-ff', um den Kontext zu erhalten.
- ✗'git merge --abort' nach dem manuellen Lösen von Konflikten verwirft die ganze Lösungsarbeit.
- ✗In den falschen Branch mergen. Prüfe vor dem Mergen immer mit 'git branch', dass du auf dem richtigen Ziel-Branch bist.
FAQ
Merge bewahrt die Historie und erzeugt einen Merge-Commit. Rebase schreibt die Historie linear um. Nutze merge für geteilte Branches, rebase zum lokalen Aufräumen.
Nutze --no-ff, wenn du Feature-Branches in main mergst. Es erzeugt einen Merge-Commit, der festhält, wann das Feature integriert wurde – auch wenn ein Fast-Forward möglich gewesen wäre.
Wenn nicht gepusht: git reset --hard ORIG_HEAD (funktioniert auch bei Fast-Forwards; verwirft nicht committete Änderungen). Wenn gepusht: git revert -m 1 <merge-commit>, um einen neuen Commit zu erzeugen, der den Merge rückgängig macht.
Ein Fast-Forward passiert, wenn dein Branch seit dem Abzweigpunkt keine neuen Commits hat. Git schiebt einfach den Zeiger vor, statt einen Merge-Commit zu erzeugen.
Öffne die Konfliktdateien, suche die <<<<<<<-Marker, behalte den gewünschten Code, entferne die Marker, dann git add auf die Dateien und git merge --continue.
Ein normaler Merge bewahrt die ganze Commit-Historie. Ein Squash-Merge fasst alles zu einem Commit zusammen. Nutze Squash, wenn der Feature-Branch unordentliche WIP-Commits hat, die du nicht in main willst.