Arbeiten mit Branches

Git Merge-Strategieoptionen und Beispiele

Wenn ein Teil der Arbeit fertiggestellt, getestet und bereit für die Durchführung des Merge in die Hauptentwicklungslinie ist, muss dein Team einige Strategieentscheidungen treffen. Was sind eure Merge-Strategieoptionen? In diesem Artikel sehen wir uns die Möglichkeiten an und erläutern, wie Atlassian arbeitet. Am Ende haben wir Ihnen hoffentlich einige Hilfsmittel an die Hand gegeben, anhand derer du entscheiden kannst, was für dein Team am besten funktioniert.

Git Merge-Strategien

Ein Merge findet statt, wenn zwei Branches kombiniert werden. Git nimmt dazu zwei (oder mehr) Commit-Pointer und versucht, einen gemeinsamen Basis-Commit zu erstellen. Git hat dabei verschiedene Verfahren, einen Basis-Commit zu finden. Diese werden "Merge-Strategien" genannt. Sobald Git einen gemeinsamen Basis-Commit findet, wird ein neuer "Merge-Commit" erstellt, der Änderungen der angegebenen Merge-Commits kombiniert. Technisch gesehen ist ein Merge-Commit ein normaler Commit, bei dem es nur zwei Vorgänger-Commits gibt.

git merge wählt automatisch eine Merge-Strategie aus, außer es ist eine spezielle Strategie angegeben. Die Befehle git merge und git pull können an die Option -s (Strategie) weitergegeben werden. An die Option -s kann der Name der gewünschten Merge-Strategie einfach angehängt werden. Wenn nicht anderweitig angegeben, wählt Git die am besten geeignete Merge-Strategie basierend auf den bereitgestellten Branches aus. Nachfolgend findest du eine Liste der verfügbaren Merge-Strategien.

Recursive

git merge -s recursive branch1 branch2

Diese Option funktioniert mit zwei Heads. Recursive ist die standardmäßige Merge-Strategie, wenn für einen Branch ein Pull gezogen oder ein Merge durchgeführt wird. Zusätzlich kann mit dieser Option ein Merge mit Umbenennungen erkannt und abgewickelt werden. Es ist momentan jedoch noch nicht möglich, erkannte Kopien zu nutzen. Dies ist die Standard-Merge-Strategie, wenn für einen Branch ein Pull oder ein Merge durchgeführt wird.

Erledigen

git merge -s resolve branch1 branch2

Diese Option kann zwei Heads mithilfe eines 3-Wege-Merge-Algorithmus erledigen. Dabei wird vorsichtig versucht, Mehrdeutigkeiten über Kreuz zusammenzuführen, was im Allgemeinen als schnell und sicher gilt.

Octopus

git merge -s octopus branch1 branch2 branch3 branchN

Die standardmäßige Merge-Strategie für mehr als zwei Heads. Octopus wird automatisch ausgeführt, wenn mehr als ein Branch weitergegeben wird. Falls ein Merge Konflikte hat, die manuell gelöst werden müssen, lehnt Octopus den Merge-Versuch ab. Diese Option wird primär dafür eingesetzt, ähnliche Feature-Branch-Heads zusammenzufassen.

Ours

git merge -s ours branch1 branch2 branchN

Die Ours-Strategie arbeitet mit einer Anzahl N von Branches. Das ausgegebene Merge-Ergebnis ist immer das des aktuellen Branch-HEAD. Der Begriff "ours" impliziert, dass bevorzugt alle Änderungen von anderen Branches ignoriert werden. Diese Option ist dazu gedacht, den Verlauf von ähnlichen Feature-Branches zusammenzuführen.

Subtree

git merge -s subtree branchA branchB

Diese Option ist eine Erweiterung der Recursive-Strategie. Wenn B eine Unterstruktur von A ist, wird beim Mergen von A und B zunächst B aktualisiert, um die Baumstruktur von A abzubilden. Dieses Update wird dann ebenfalls im gemeinsamen Vorgängerbaum durchgeführt, der A und B gemeinsam ist.

Typen von Git Merge-Strategien

Explicit-Merges

Ein Explicit-Merge ist der standardmäßige Merge-Typ. Der "explicit"-Teil besteht darin, dass ein neuer Merge-Commit erstellt wird. Damit wird der Commit-Verlauf verändert und explizit angezeigt, wenn ein Merge durchgeführt wurde. Der Inhalt des Merge-Commit wird also ersichtlich, da angezeigt wird, welche Commit-Vorgänge die Vorgänge des Merge-Commit waren. Manche Teams vermeiden explizite Merges, da durch die Merge-Commits "zusätzliche" Vorgänge in den Verlauf des Projekts hinzugefügt werden.

Implicit-Merge über Rebase oder Fast-Forward-Merge

Während bei Explicit-Merges ein Merge-Commit erzeugt wird, ist dies bei Implicit-Merges nicht der Fall. Ein Implicit-Merge nimmt eine Reihe von Commits eines angegebenen Branch-Head und wendet diese auf den obersten Knoten eines Ziel-Branches an. Implicit-Merges werden durch Rebase Events oder Fast-Forward-Merges ausgelöst. Ein Implicit-Merge ist eine Ad-hoc-Auswahl von Commits eines angegebenen Branches.

Squash bei Merge, in der Regel ohne Explicit-Merge

Eine weitere Variante eines Implicit-Merge ist ein Squash. Ein Squash kann während eines interaktiven Rebase erfolgen. Ein Squash-Merge nimmt die Commits eines Ziel-Branch und kombiniert bzw. "quetscht" diese in einen Commit-Vorgang Dieser Commit wird dann auf den HEAD des Merge-Basis-Branch angewendet. Ein Squash wird im Allgemeinen verwendet, um einen "sauberen Verlauf" während eines Merge zu erhalten. Der Ziel-Merge-Branch kann einen vollen Verlauf mit häufigen Commits aufweisen. Wird ein Squash ausgeführt und der Commit-Verlauf des Ziel-Branches damit zusammengefasst, wird der Verlauf zu einem einzelnen, reduzierten "Branch-Commit". Diese Technik ist bei Git-Workflows hilfreich, die Feature-Branches nutzen.

Recursive Git Merge-Strategieoptionen

Die oben vorgestellte "Recursive"-Strategie hat eine eigene Gruppe zusätzlicher Optionen.

ours

Diese Option ist nicht mit der Merge-Strategie "Ours" zu verwechseln. Hier werden Konflikte nicht automatisch sauber gelöst, indem die "Ours"-Version favorisiert wird. Änderungen auf Seiten der "anderen" Branches werden automatisch integriert, wenn keine Konflikte bestehen.

theirs

Die andere Seite bei der "Ours"-Strategie. Bei der Option "Theirs" wird der fremde Merge-Baum bei der Konfliktlösung bevorzugt.

patience

Bei dieser Option ist zusätzliche Zeit dafür vorgesehen, fehlerhafte Merges von unwichtigen passenden Zeilen zu vermeiden. Diese Option wird vorzugsweise eingesetzt, wenn die zu mergenden Branches sehr unterschiedlich sind.

diff-algorithim

Bei dieser Option kann ein expliziter diff-Algorithmus angegeben werden. Der diff-Algorithmus wird mit dem git diff Befehl mitgegeben.

ignore-*

    ignore-space-change
    ignore-all-space
    ignore-space-at-eol
    ignore-cr-at-eol

Eine Reihe von Optionen für Leerzeichen. Alle Zeilen, die Teil der angegebenen Option sind, werden ignoriert.

renormalize

Mit dieser Option werden im Zuge eines 3-Wege-Merge alle drei Git-Bäume aus- und wieder eingecheckt. Diese Option ist dazu gedacht, Branches mit unterschiedlichen Check-in/Check-out-Status zu mergen.

no-normalize

Deaktiviert die Option zur erneuten Normalisierung. Dadurch wird die merge.renormalize-Konfigurationsvariable überschrieben.

no-renames

Diese Option ignoriert beim Merge umbenannte Dateien.

find-renames=n

Diese Option ist das standardmäßige Verhalten. Der rekursive Merge berücksichtigt umbenannte Dateien. Der Parameter n kann verwendet werden, um einen Schwellenwert für die Umbenennung von Entsprechungen weiterzugeben. Der Standardwert für n ist 100 %.

subtree

Diese Option basiert auf der "Subtree"-Strategie. Während dabei für zwei Bäume ein Merge durchgeführt und dieser bearbeitet wird, damit beide zu einem gemeinsamen Vorgänger passen, zielt diese Strategie auf die Verzeichnis-Metadaten der Struktur ab, um eine Übereinstimmung zu erreichen.

Unsere Git Merge-Richtlinie

Atlassian bevorzugt Explicit Merges. Der Grund dafür ist sehr einfach: Explicit Merges bieten eine gute Nachverfolgbarkeit und Kontext zu den Features, die zusammengeführt werden. Eine Bereinigung des lokalen Verlaufs vor dem Teilen eines Feature-Branches für die Prüfung durch Rebase wird unbedingt empfohlen, dies ändert jedoch nichts an der allgemeinen Richtlinie. Sie wird nur dadurch ergänzt.

Möchtest du Branching ausprobieren?

Sieh dir dieses interaktive Tutorial an.

Jetzt loslegen