W3docs

Merge-Strategien

Git Merge-Strategien erklärt — ort, recursive, resolve, octopus, ours und subtree — plus Fast-Forward, Squash und explizite Merges mit Beispielen.

mergeconflicts

Git Merge-Strategien

Wenn die Arbeit an einem Branch abgeschlossen und bereit ist, mit der Hauptentwicklungslinie zusammengeführt zu werden, muss Git entscheiden, wie die beiden Historien miteinander verbunden werden sollen. Der dabei verwendete Algorithmus wird als Merge-Strategie bezeichnet.

Eine Merge-Strategie nimmt zwei (oder mehr) Branch-Spitzen und erzeugt ein einzelnes Ergebnis. Meistens muss man eine Strategie nicht explizit benennen — der git merge-Befehl wählt automatisch einen sinnvollen Standard, basierend darauf, wie viele Branches zusammengeführt werden und ob ihre Historien auseinandergelaufen sind. Wenn Sie Kontrolle benötigen, übergeben Sie -s <strategy> (und optional -X <strategy-option> zur Feinabstimmung):

git merge -s recursive feature

Diese Seite behandelt zwei verwandte Konzepte, die leicht verwechselt werden können:

  • Merge-Strategien (-s): der Algorithmus, der den zusammengeführten Baum berechnet — ort, recursive, resolve, octopus, ours, subtree.
  • Merge-Typen: die Art des Ergebnisses, das Sie erhalten — ein expliziter Merge-Commit, ein Fast-Forward oder ein Squash.

In den meisten Fällen müssen Sie eine Strategie nicht manuell auswählen. Die Standardeinstellungen sind für die überwiegende Mehrheit der Merges korrekt; greifen Sie auf -s oder -X nur zurück, wenn ein konkretes Problem vorliegt, das diese lösen.

Merge-Strategie-Algorithmen

ort (Standard)

git merge -s ort feature

ort ("Ostensibly Recursive's Twin") ist seit Git 2.34 (2021) die Standard-Merge-Strategie für zwei Heads. Es handelt sich um eine schnellere und korrektere Neuimplementierung der älteren recursive-Strategie und erzeugt dasselbe Ergebnis: einen 3-Wege-Merge, der Umbenennungen erkennt und mehrere gemeinsame Vorfahren rekursiv zu einem einzigen virtuellen Vorfahren zusammenführt.

Da es der Standard ist, wird ort automatisch verwendet, wenn Sie einen einfachen Merge ausführen:

git checkout main
git merge feature

recursive

git merge -s recursive feature

Die ursprüngliche 3-Wege-Strategie zum Zusammenführen zweier Branches und der Standard vor Git 2.34. Sie kann Umbenennungen erkennen und nachverfolgen, jedoch keine erkannten Dateikopien nutzen. Heutzutage muss man sie kaum noch explizit anfordern — ort hat sie abgelöst — sie ist jedoch weiterhin aus Kompatibilitätsgründen verfügbar.

resolve

git merge -s resolve feature

resolve führt einen einfachen 3-Wege-Merge zwischen genau zwei Heads durch (dem aktuellen Branch und dem angegebenen). Es versucht nicht, intelligent mit mehreren Merge-Basen umzugehen, was es schnell und vorhersehbar macht, aber es kann bei einer "Kreuzverflechtungs"-Historie, in der zwei Branches zuvor gegenseitig zusammengeführt wurden, zu Fehlzusammenführungen kommen. Verwenden Sie es nur, wenn der recursive/ort-Merge ein Ergebnis liefert, das Sie mit einem einfacheren Algorithmus überprüfen möchten.

octopus

git merge -s octopus topic-a topic-b topic-c

octopus ist die Standard-Strategie, wenn Sie mehr als zwei Branches gleichzeitig zusammenführen. Es bündelt mehrere Branch-Spitzen in einem einzigen Merge-Commit, was beim Verbinden einer Reihe unabhängiger Topic-Branches praktisch ist. Es verweigert jedoch absichtlich jeden Merge, der eine manuelle Konfliktlösung erfordern würde — Octopus-Merges sollen sauber sein, daher sollten Sie die Branches einzeln zusammenführen, wenn ein Konflikt besteht.

ours

git merge -s ours obsolete-branch

Die ours-Strategie erstellt einen Merge-Commit, der den anderen Branch als Elternteil hat, aber den Baum des aktuellen Branches vollständig unverändert lässt — alle Änderungen aus dem anderen Branch werden verworfen. Der typische Anwendungsfall ist, einen Branch aus historischen Gründen als "gemergt" zu markieren (damit zukünftige Merges davon wissen), während sein tatsächlicher Inhalt ignoriert wird — beispielsweise beim Ausmustern eines langlebigen Branches, dessen Arbeit nicht mehr benötigt wird.

Warnung

Verwechseln Sie nicht die ours-Strategie (-s ours, die den Inhalt des anderen Branches vollständig verwirft) mit der ours-Strategie-Option (-X ours, die Ihre Seite nur bei tatsächlich konfliktierenden Zeilen bevorzugt). Sie verhalten sich sehr unterschiedlich.

subtree

git merge -s subtree project-b

subtree ist eine Variante des recursive/ort-Algorithmus für den Fall, dass ein Baum ein Unterverzeichnis (ein "Subtree") des anderen ist. Vor dem Merge verschiebt Git die Pfade eines Baums so, dass die beiden übereinstimmen, und führt dann wie gewohnt zusammen. Dies ist der Mechanismus hinter dem Einbinden eines Projekts in einen Unterordner eines anderen. Für alltägliche Subtree-Arbeiten ist der übergeordnete git subtree-Befehl in der Regel einfacher.

Merge-Typen: Wie das Ergebnis aussieht

Die Strategie entscheidet, wie die Bäume kombiniert werden; der Merge-Typ beschreibt die Form der Historia, die dabei entsteht.

Fast-Forward-Merge

Wenn der Branch, in den Sie zusammenführen, sich seit der Erstellung des anderen Branches nicht verändert hat, gibt es nichts zu kombinieren — Git kann einfach den Branch-Zeiger auf den neuesten Commit vorrücken. Es wird kein neuer Commit erstellt und die Historie bleibt vollständig linear. Dies ist Gits Standard, wann immer es möglich ist:

git checkout main
git merge feature
# Output (when main is an ancestor of feature):
# Updating a1b2c3d..d4e5f6a
# Fast-forward
#  app.js | 3 +++
#  1 file changed, 3 insertions(+)

Um auch dann eine explizite Aufzeichnung des Merges zu behalten, wenn ein Fast-Forward möglich ist, erzwingen Sie einen Merge-Commit mit --no-ff:

git merge --no-ff feature

Expliziter (3-Wege) Merge-Commit

Wenn beide Branches neue Commits haben — ihre Historien auseinandergelaufen sind — erstellt Git einen brandneuen Merge-Commit mit zwei Elternteilen. Dieser ist "explizit", weil der Commit in der Historia sichtbar ist und genau festhält, wo und wann die Branches zusammengekommen sind:

git checkout main
git merge feature
# Output (when histories diverged):
# Merge made by the 'ort' strategy.
#  app.js | 5 +++++
#  1 file changed, 5 insertions(+)

Wenn die beiden Branches dieselben Zeilen geändert haben, stoppt der Merge mit einem Konflikt, den Sie manuell auflösen müssen — siehe Merge-Konflikte.

Squash-Merge

Ein Squash-Merge fasst alle Commits aus dem Quell-Branch in einem einzigen neuen Commit auf dem aktuellen Branch zusammen. Es wird kein Merge-Commit erstellt und der Quell-Branch wird nicht als Elternteil erfasst, sodass die einzelnen Commits des Quell-Branches nie in der Ziel-Historia erscheinen:

git checkout main
git merge --squash feature
# Changes are staged but NOT committed yet:
git commit -m "Add feature X"

Dadurch bleibt die Historia des Haupt-Branches übersichtlich — ein Commit pro Feature — auf Kosten des detaillierten Commit-Logs des Feature-Branches. Dies ist eine beliebte Richtlinie für Pull Requests. Um Commits innerhalb eines Branches umzuschreiben, siehe interaktives Rebase.

Strategie-Optionen (-X)

Die ort/recursive-Strategien akzeptieren zusätzliche Optionen über das -X-Flag (beachten Sie das große X, getrennt von -s). Um Konflikte beispielsweise automatisch zugunsten Ihrer Seite aufzulösen:

git merge -X ours feature

Die verfügbaren Optionen sind:

OptionAuswirkung
oursLöst konfliktierende Abschnitte automatisch zugunsten unserer Seite auf. Nicht konfliktierende Änderungen aus dem anderen Baum werden weiterhin zusammengeführt. (Im Gegensatz zu -s ours, das die andere Seite vollständig verwirft.)
theirsDas Gegenteil von ours: löst Konflikte automatisch zugunsten des anderen Baums auf. Es gibt keine separate theirs-Strategie, nur diese Option.
patienceVerwendet mehr Zeit für den Zeilenabgleich, um Fehlzusammenführungen durch unwichtige übereinstimmende Zeilen zu vermeiden.
diff-algorithm=<algo>Weist den Merge an, einen anderen Diff-Algorithmus zu verwenden (z. B. histogram, minimal, patience).
ignore-space-change / ignore-all-spaceIgnoriert reine Leerzeichen-Unterschiede bei der Konflikterkennung. Mit echten Änderungen gemischte Leerzeichen werden nicht ignoriert.
renormalizeFührt ein virtuelles Aus- und Einchecken aller Dateistadien durch, nützlich wenn sich Zeilenenden oder Smudge/Clean-Filter geändert haben.
no-renormalizeDeaktiviert die renormalize-Option.
no-renamesSchaltet die Umbenennungserkennung während des Merges aus.
find-renames=<n>Aktiviert die Umbenennungserkennung mit einem Ähnlichkeitsschwellenwert von n% (Standard 50%).
subtree=<path>Ähnlich wie die Subtree-Strategie, erlaubt aber die Angabe des Pfadpräfixes, der verschoben werden soll, um die Bäume zur Deckung zu bringen.

Wie man wählt

Für die alltägliche Arbeit wählen Sie keine Strategie — lassen Sie Git ort verwenden und entscheiden Sie nur das gewünschte Ergebnis:

  • Einfachste, lineare Historia wenn möglich? Einfach git merge (Fast-Forward automatisch).
  • Jeden Merge als Commit festhalten? --no-ff hinzufügen.
  • Einen sauberen Commit pro Feature auf main? --squash verwenden.
  • Mehrere fertige Topic-Branches auf einmal verbinden? git merge a b c verwendet automatisch octopus.

Wenn Sie Ihre Commits lieber auf den Ziel-Branch anwenden möchten, anstatt zu mergen, schauen Sie sich git rebase an. Um einen einzelnen Commit aus einem anderen Branch zu übernehmen, verwenden Sie git cherry-pick.

Übungen

Übung
What are the different merge strategies in Git and their characteristics?
What are the different merge strategies in Git and their characteristics?
Was this page helpful?