Git merge
In Git kannst du einen geforkten Verlauf per Merging wieder zusammensetzen. Mit dem Befehl git merge
kannst du die unabhängigen Entwicklungszweige, die mit git branch
erstellt wurden, in einen einzigen Branch integrieren.
Beachte, dass alle folgenden Befehle in den aktuellen Branch gemergt werden. Der aktuelle Branch wird aktualisiert, um den Projektstand des Merges wiederzugeben, doch der Ziel-Branch bleibt davon komplett unberührt. Zur Erinnerung: Der Befehl git merge
wird also oft im Zusammenhang mit git checkout
zum Auswählen des aktuellen Branches und git branch -d
zum Löschen des veralteten Ziel-Branches genutzt.
Wie funktioniert "git revert"?
Mit git merge
werden mehrere Commit-Abfolgen in einen einheitlichen Verlauf zusammengeführt. Vor allem wird git merge
genutzt, um zwei Branches zu vereinen. Auf dieses Branch-Merging-Muster konzentrieren sich die folgenden Beispiele. In diesen Fällen sucht git merge
zwischen zwei Commit-Pointern, was für gewöhnlich die Branch-Spitzen sind, einen gemeinsamen Basis-Commit. Sobald Git den gemeinsamen Basis-Commit gefunden hat, wird ein neuer "Merge-Commit" erstellt, um die Änderungen jeder Abfolge von Merge-Commits in der Warteschlange zusammenzuführen.
Nehmen wir an, wir haben ein neues Branch-Feature, das auf Basis des main
-Branches erstellt wurde. Wir wollen diesen Feature-Branch nun in den main
-Branch mergen.
Zugehöriges Material
Git-Protokoll für Fortgeschrittene
Lösung anzeigen
Git kennenlernen mit Bitbucket Cloud
Mit diesem Befehl wird das angegebene Branch-Feature in den aktuellen Branch, den sogenannten main
-Branch, gemergt. Git bestimmt den Merging-Algorithmus automatisch (später mehr dazu).
Merge-Commits haben zwei übergeordnete Commits und unterscheiden sich damit von anderen Commits. Git versucht beim Erstellen eines Merge-Commits ganz automatisch, die separaten Verläufe zu mergen. Daten, die in beiden Verläufen geändert wurden, können von Git nicht automatisch zusammengeführt werden. Dieses Szenario führt in Git zu einem Versionskontrollkonflikt und erfordert den Eingriff des Benutzers.
Vorbereitung auf das Mergen
Damit das Mergen problemlos funktioniert, solltest du vorbereitend einige Schritte durchführen.
Den Merge-Ziel-Branch bestätigen
Führe git status
aus, um sicherzustellen, dass der HEAD
auch auf den Branch verweist, der wirklich das Ziel des Merge-Prozesses ist. Falls erforderlich, kannst du mit git checkout
zu dem Branch wechseln, der das Merge-Ziel sein soll. In diesem Fall führen wir git checkout main
aus.
Neueste Remote-Commits abrufen
Stelle sicher, dass der Merge-Ziel-Branch und der Merging-Branch mit den neuesten Remote-Änderungen aktualisiert wurden. Mit git fetch
kannst du die neuesten Remote-Commits pullen. Vergewissere dich nach dem Abrufen der Commits, dass der main
-Branch über die neuesten Updates verfügt, indem du git pull
ausführst.
Verschmelzung
Wenn die zuvor beschriebenen Schritte zur Vorbereitung auf das Mergen abgeschlossen sind, kann der Merge-Vorgang beginnen. Führe dazu git merge
aus, wobei
der Name des Branches ist, der in den Merge-Ziel-Branch gemergt wird.
Fast-Forward-Merge
Ein Fast-Forward-Merge findet statt, wenn ein linearer Pfad von der Spitze des aktuellen Branches zum Ziel-Branch existiert. Statt die Branches tatsächlich zusammenzuführen, muss Git zur Integration der verschiedenen Verläufe lediglich die Spitze des aktuellen Branches an die Spitze des Ziel-Branches verschieben ("fast-forward"). Dadurch werden die Verläufe miteinander kombiniert, und alle Commits aus dem Ziel-Branch sind auch über den aktuellen Branch zugänglich. Ein Fast-Forward-Merge eines Features in den main
-Branch könnte etwa so aussehen:
Ein Fast-Forward-Merge ist jedoch nicht möglich, wenn die Branches voneinander abweichen. Wenn kein linearer Pfad zum Ziel-Branch existiert, kann Git die Branches nur mithilfe eines 3-Way-Merges zusammenführen. Für 3-Way-Merges gibt es einen speziellen Commit, um die beiden Verläufe miteinander zu verknüpfen. Die Benennung geht darauf zurück, dass Git drei Commits zum Durchführen des Merge-Commits verwendet: für die beiden Branch-Spitzen und ihren gemeinsamen Vorgänger.
Beide Merge-Strategien stehen dir offen. Viele Entwickler bevorzugen jedoch Fast-Forward-Merges (mit Unterstützung von Rebasing) für kleine Features oder Bugfixes und greifen nur zur Integration langlebigerer Features auf 3-Way-Merges zurück. Bei der letzten Strategie dient der entstehende Merge-Commit zum symbolischen Zusammenführen der beiden Branches.
Unser erstes Beispiel zeigt einen Fast-Forward-Merge. Mit dem Code unten werden ein neuer Branch erstellt, zwei Commits zu diesem Branch hinzugefügt und der Branch dann mit einem Fast-Forward-Merge in den Hauptzweig integriert.
# Start a new feature
git checkout -b new-feature main
# Edit some files
git add <file>
git commit -m "Start a feature"
# Edit some files
git add <file>
git commit -m "Finish a feature"
# Merge in the new-feature branch
git checkout main
git merge new-feature
git branch -d new-feature
Dieser Workflow ist für kurzlebige Themen-Branches üblich, die weniger als Organisationstool für langlebigere Features als vielmehr zur isolierten Entwicklung genutzt werden.
Außerdem sollte Git bei git branch -d
kein Problem melden, da der Zugriff auf das neue Feature (new-feature) nun vom Haupt-Branch aus möglich ist.
Falls du während eines Fast-Forward-Merges zu Dokumentationszwecken einen Merge-Commits durchführen musst, führe git merge
mit der Option --no-ff
aus.
git merge --no-ff <branch>
Mit diesem Befehl wird der angegebene Branch in den aktuellen Branch gemergt. Dabei wird immer ein Merge-Commit erzeugt (auch bei Fast-Forward-Merges). Das ist nützlich, wenn du alle Merges in deinem Repository dokumentieren willst.
3-Way-Merge
Das nächste Beispiel ist sehr ähnlich. Hier ist jedoch ein 3-Way-Merge erforderlich, weil der main
-Branch fortgeführt und gleichzeitig das Feature bearbeitet wird. Dieses Szenario kommt häufig vor, wenn es um umfangreiche Features geht oder mehrere Entwickler zeitgleich an einem Projekt arbeiten.
Start a new feature
git checkout -b new-feature main
# Edit some files
git add <file>
git commit -m "Start a feature"
# Edit some files
git add <file>
git commit -m "Finish a feature"
# Develop the main branch
git checkout main
# Edit some files
git add <file>
git commit -m "Make some super-stable changes to main"
# Merge in the new-feature branch
git merge new-feature
git branch -d new-feature
Beachte, dass es für Git unmöglich ist, einen Fast-Forward-Merge durchzuführen, da der main
-Branch ohne Zurückverfolgung nicht zu new-feature
verschoben werden kann.
In den meisten Workflows wäre new-feature
ein viel größeres Feature mit einer langen Entwicklungszeit. Daher würden neue Commits in der Zwischenzeit im main
-Branch erscheinen. Wenn dein Feature-Branch aber denselben Umfang hat wie im Beispiel oben, würdest du ihn wahrscheinlich besser auf den main
-Branch rebasen und einen Fast-Forward-Merge durchführen. So vermeidest du, dass unnötige Merge-Commits den Projektverlauf aufblähen.
Konflikte lösen
Wenn du versuchst, zwei Branches zu mergen, und es in beiden Branches Änderungen in demselben Teil derselben Datei gibt, dann weiß Git nicht, welche Version übernommen werden soll. In einer solchen Situation wird der Vorgang vor dem Merge-Commit angehalten und du kannst den Konflikt manuell lösen.
Das Tolle am Merging-Prozess in Git: Mit dem gewohnten Workflow zum Bearbeiten, Stagen und Durchführen von Commits kannst du auch Merge-Konflikte lösen. Führe bei einem Merge-Konflikt einfach den Befehl git status
aus und die betroffenen Dateien werden angezeigt. Wenn zum Beispiel in beiden Branches derselbe Abschnitt von hello.py
geändert wurde, wird dir in etwa Folgendes angezeigt:
On branch main
Unmerged paths:
(use "git add/rm ..." as appropriate to mark resolution)
both modified: hello.py
Darstellung von Konflikten
Wenn Git während eines Merge-Vorgangs einen Konflikt feststellt, werden in den betroffenen Dateien Anfang und Ende der Inhalte, die in Konflikt stehen, optisch gekennzeichnet. Die optische Kennzeichnung sieht wie folgt aus: <<<<<<<, =======, und >>>>>>>. Es ist hilfreich, während eines Merges nach dieser Kennzeichnung Ausschau zu halten, um mögliche Konflikte zu erkennen.
here is some content not affected by the conflict
<<<<<<< main
this is conflicted text from main
=======
this is conflicted text from feature branch
>>>>>>> feature branch;
Im Allgemeinen handelt es sich bei dem Inhalt vor der Kennzeichnung =======
um den Merge-Ziel-Branch, während der Teil danach der Merging-Branch ist.
Sobald du ausgemacht hast, welche Abschnitte in Konflikt stehen, kannst du den Merge nach deinen Vorstellungen korrigieren. Wenn du den Merge abgeschlossen hast, musst du lediglich den Befehl git add
auf die in Konflikt stehende(n) Datei(en) ausführen, um Git zu sagen, dass sie gelöst sind. Anschließend führst du einen normalen git commit
aus, um den Merge-Commit zu erzeugen. Der Prozess ist derselbe wie beim Committen eines gewöhnlichen Snapshots. Normale Entwickler können eigene Merges also ganz einfach verwalten.
Beachte, dass es nur bei 3-Way-Merges zu Merge-Konflikten kommt. In Fast-Forward-Merges können keine Änderungskonflikte entstehen.
Zusammenfassung
Dieses Dokument bietet einen Überblick über den Befehl git merge
. Das Mergen ist bei der Arbeit mit Git ein wesentlicher Prozess. Wir haben die internen Mechanismen hinter dem Merging und die Unterschiede zwischen einem Fast-Forward-Merge und einem echten sogenannten 3-Way-Merge behandelt. Das sind einige der wichtigsten Punkte:
1. Durch das Mergen in Git werden mehrere Commit-Abfolgen in einen einheitlichen Commit-Verlauf zusammengeführt.
2. Es gibt allgemein gesehen zwei Merging-Möglichkeiten in Git: Fast-Forward- und 3-Way-Merging.
3. Git kann Commits automatisch mergen, vorausgesetzt, es gibt keine Änderungen, die zu Konflikten mit beiden Commit-Abfolgen führen.
In diesem Dokument werden andere Git-Befehle integriert und referenziert, wie: git branch, git pull und git fetch. Weitere Informationen findest du auf den entsprechenden eigenständigen Seiten.
Diesen Artikel teilen
Nächstes Thema
Lesenswert
Füge diese Ressourcen deinen Lesezeichen hinzu, um mehr über DevOps-Teams und fortlaufende Updates zu DevOps bei Atlassian zu erfahren.