Bei der Arbeit, die in einem Entwicklungsprojekt stattfindet, ist Git ein Geschenk des Himmels. Wenn du jedoch viele Leute auf der Tanzfläche hast, werden sich ein oder zwei von ihnen gegenseitig auf die Füße treten. Für dein Projekt bedeutet das, dass zwei Entwickler an derselben Code-Suite arbeiten und beide einen Commit machen. In solchen Situationen musst du einige Git-Merge-Strategien anwenden, um den Konflikt zu lösen.

Ein Git Merge kann ganz einfach sein, aber es gibt auch viele andere Situationen, in denen du einen fortgeschrittenen Ansatz brauchst. In diesem Fall musst du Strategien wie rekursives Zusammenführen, Drei-Wege-Merge und viele mehr anwenden. Es kann sogar sein, dass du einen Git-Merge irgendwann wieder rückgängig machen musst.

In diesem Leitfaden werden wir einige komplexe Git-Merge-Techniken besprechen, die du in deinen Werkzeuggürtel aufnehmen kannst. Lass uns gleich mit den guten Dingen anfangen!!

Eine Einführung in die Git Merge-Strategien

Das Grundkonzept eines Merge ist einfach: Du fügst zwei Zweige zusammen, um aus mehreren Commits einen zu machen. Es gibt jedoch eine Reihe von Techniken, die du anwenden kannst, um sicherzustellen, dass du den richtigen Code festlegst und zusammenführst.

Wir werden uns ein paar wichtige Strategien ansehen, die du verstehen musst. Sie stehen nicht in einer bestimmten Reihenfolge, und irgendwann in deiner Entwickler-Karriere wirst du sie alle brauchen. Außerdem brauchst du ein solides Verständnis der grundlegenden Git-Konzepte wie Zeiger, Zweige und Commits.

Der Unterschied zwischen Zwei-Wege- und Drei-Wege-Merges

Es ist hilfreich, den Unterschied zwischen einem Zwei-Wege-Merge und dem Drei-Wege-Merge zu kennen. Die meisten der Merge-Strategien, die wir im Folgenden behandeln, beziehen sich auf Drei-Wege-Situationen. Tatsächlich ist es einfacher, darüber zu sprechen, was ein Drei-Wege-Merge ist. Nimm das folgende Beispiel:

  • Du hast einen Hauptzweig mit mehreren Commits und einen Funktionszweig, der ebenfalls Commits hat.
  • Wenn der Hauptzweig nun weitere Commits vornimmt, laufen beide Zweige auseinander.
  • Laienhaft ausgedrückt: Sowohl der Haupt- als auch der Funktionszweig haben Commits, die der andere nicht hat. Wenn du diese in beide Richtungen zusammenführst, verlierst du einen Commit (wahrscheinlich auf main).
  • Stattdessen erstellt Git einen neuen Merge-Commit aus dem aktuellen Haupt- und Feature-Zweig.

Kurz gesagt: Git betrachtet drei verschiedene Snapshots, um Änderungen zusammenzuführen: den Kopf des Hauptzweigs, den Kopf des Funktionszweigs und den gemeinsamen Vorgänger. Dies ist der letzte gemeinsame Commit für den Haupt- und den Funktionszweig.

In der Praxis wirst du dir keine Gedanken darüber machen müssen, ob eine bestimmte Zusammenführungsstrategie zwei- oder dreifach ist. In vielen Fällen musst du eine Strategie unabhängig davon verwenden. In jedem Fall ist es hilfreich zu wissen, wie Git „denkt“, wenn es um das Zusammenführen von Zweigen und Repos geht.

Fast-Forward Merging

Bei der ersten Strategie musst du vielleicht gar nichts tun, um sie auszuführen. Ein Fast-Forward-Merge verschiebt den Zeiger auf den letzten Commit auf Main , ohne einen zusätzlichen Commit zu erstellen (was verwirrend sein kann).

Die Technik beginnt mit einem Hauptzweig, der Commits haben kann oder auch nicht. In diesem Fall eröffnest du einen neuen Zweig, arbeitest an dem Code und machst Commits. An diesem Punkt musst du die Änderungen auch wieder mit dem Hauptzweig zusammenführen. Ein Fast-Forward-Merge hat nur eine Voraussetzung: Du musst sie erfüllen:

  • Du musst sicherstellen, dass keine anderen Änderungen an der Hauptversion vorgenommen werden, während du an deinem neuen Zweig arbeitest.

Das wird nicht immer möglich sein, vor allem wenn du in einem großen Team arbeitest. Wenn du jedoch deine Commits mit einem aktuellen Hauptzweig zusammenführst, der keine eigenen Commits hat, wird ein Fast-Forward-Merge durchgeführt. Du kannst dies auf verschiedene Arten tun:

git merge <branch>

git merge --ff-only

In vielen Fällen musst du nicht angeben, dass du einen Fast-Forward-Merge durchführen willst. Diese Art des Merge kommt bei Einzelprojekten oder bei Projekten mit kleinen Teams vor. In einer schnelllebigen Umgebung ist dies ein seltener Merge. Andere Zusammenführungen sind daher häufiger.

Recursive Merging

Ein rekursiver Merge ist oft der Standard, da er häufiger vorkommt als andere Arten von Zusammenschlüssen. Bei einem rekursiven Merge machst du Commits auf einem Zweig, aber weitere Commits finden auch auf dem Main statt.

Wenn es an der Zeit ist, zu mergen, rekursiert Git über den Zweig, um den endgültigen Commit zu machen. Das bedeutet, dass ein Merge Commit zwei Elternteile hat, sobald du ihn abgeschlossen hast.

Wie bei einem Fast-Forward-Merge musst du normalerweise keinen rekursiven Merge angeben. Du kannst jedoch mit den folgenden Befehlen und Flags dafür sorgen, dass Git sich nicht für einen Fast-Forward-Merge entscheidet:

git merge --no-ff

git merge -s recursive <branch1> <branch2>

Die zweite Zeile verwendet die Option -s strategy und die explizite Benennung, um einen Merge auszuführen. Im Gegensatz zu einem Fast-Forward-Merge wird bei einem rekursiven Merge ein eigener Merge-Commit erstellt. Für bidirektionale Zusammenführungen ist eine rekursive Strategie solide und funktioniert gut.

Ours and Theirs

Eine häufige Situation während der Entwicklung ist, dass du eine neue Funktion in deinem Projekt erstellst, die letztendlich kein grünes Licht bekommt. In vielen Fällen musst du eine Menge Code zusammenführen, der ebenfalls voneinander abhängig ist. Ein „Ours“-Merge ist die beste Möglichkeit, diese Konflikte zu lösen.

Diese Art des Zusammenführens kann so viele Zweige wie nötig verarbeiten und ignoriert alle Änderungen in den anderen Zweigen. Sie ist ideal, wenn du alte Funktionen oder unerwünschte Entwicklungen aus dem Weg räumen willst. Hier ist der Befehl, den du brauchst:

git merge -s ours <branch1> <branch2>

Ein „Ours“-Merge bedeutet im Wesentlichen, dass der aktuelle Zweig den Code de jure enthält. Das ist vergleichbar mit den „Theirs“-Zusammenführungen, bei denen der andere Zweig als richtig angesehen wird. Allerdings musst du hier eine andere Strategieoption angeben:

git merge -X theirs <branch2>

Die Verwendung von „Ours“- und „Theirs“-Merges kann verwirrend sein, aber in der Regel ist es sicher, sich an die typischen Anwendungsfälle zu halten (nämlich alles im aktuellen Zweig zu behalten und den Rest zu verwerfen).

Octopus

Der Umgang mit mehreren Köpfen – d.h. das Zusammenführen von mehr als einem Zweig in einen anderen – kann ein kniffliges Szenario für einen Git Merge sein. Man könnte sagen, man braucht mehr als zwei Hände, um die Konflikte zu lösen. Das ist perfekt für einen Octopus Merge.

Oktopus-Zusammenführungen sind das genaue Gegenteil von „Ours“- und „Theirs“-Zusammenführungen. Der typische Anwendungsfall ist, dass du mehrere Commits für ähnliche Funktionen einbeziehen und zu einem einzigen zusammenführen willst. So übergibst du sie:

git merge -s octopus <branch1> <branch2>

Git lehnt einen Octopus-Merge jedoch ab, wenn du im Nachhinein eine manuelle Auflösung vornehmen musst. Bei automatischen Auflösungen ist ein Octopus Merge der Standard, wenn du mehrere Zweige zu einem einzigen zusammenführen musst.

Resolve

Der Resolve-Merge ist eine der sichersten Methoden zum Zusammenführen von Commits und eignet sich hervorragend, wenn du in einer Situation bist, in der es zu kreuzweisen Zusammenführungen kommt. Es ist auch eine schnell zu implementierende Auflösungsmethode. Du kannst diese Methode auch für komplexere Merge-Historien verwenden – aber nur für solche mit zwei Köpfen.

git merge -s resolve <branch1> <branch2>

Da ein Resolve Merge einen Drei-Wege-Algorithmus verwendet, um sowohl mit dem aktuellen Zweig als auch mit dem Zweig, aus dem du die Daten ziehst, zu arbeiten, ist er vielleicht nicht so flexibel wie andere Merge-Methoden. Aber für die Aufgabe, die du brauchst, ist ein Resolve-Merge nahezu perfekt.

Subtree

Dieses Pendant zum rekursiven Zusammenführen könnte dich verwirren. Wir werden versuchen, dies anhand eines anschaulichen Beispiels zu erklären:

  • Betrachte zunächst zwei verschiedene Bäume – X und Y. Oft handelt es sich dabei um zwei Repos.
  • Du möchtest beide Bäume zu einem einzigen zusammenführen.
  • Wenn der Baum Y mit einem der Unterbäume in X übereinstimmt, wird der Baum Y so geändert, dass er der Struktur von X entspricht.

Das bedeutet, dass eine Teilbaum-Zusammenführung fantastisch ist, wenn du mehrere Repos zu einem endgültigen Artikel zusammenführen willst. Er nimmt auch die notwendigen Änderungen am gemeinsamen „Vorgängerbaum“ der beiden Zweige vor.

git merge -s subtree <branch1> <branch2>

Kurz gesagt, ein Teilbaum-Zusammenschluss ist genau das Richtige für dich, wenn du zwei Repositories zusammenführen musst. Vielleicht fällt es dir sogar schwer zu verstehen, welche Zusammenführungsstrategie die richtige für dich ist. Später werden wir einige Tools besprechen, die dir dabei helfen können.

Davor gibt es einige fortgeschrittene Merge-Konflikte, die du lösen musst.

Wie man mit komplexeren Git-Merge-Konflikten umgeht

Beim Zusammenführen von Zweigen in Git geht es eher darum, Konflikte zu verwalten und zu lösen. Je größer dein Team und dein Projekt sind, desto größer ist die Wahrscheinlichkeit von Konflikten. Einige davon können sehr komplex und schwierig zu lösen sein.

Da Konflikte Zeit, Geld und Ressourcen verschlingen können, musst du herausfinden, wie du sie schnell im Keim ersticken kannst. In den meisten Fällen arbeiten zwei Entwickler/innen an demselben Code, und beide entscheiden sich für einen Commit.

Das kann dazu führen, dass du den Merge wegen ausstehender Änderungen gar nicht starten kannst oder dass während des Merges ein Fehler auftritt, der einen manuellen Eingriff erfordert. Sobald dein Arbeitsverzeichnis „sauber“ ist, kannst du beginnen. In vielen Fällen wird Git dich über einen Konflikt informieren, sobald du mit dem Zusammenführen beginnst:

Ein Terminal-Fenster mit Git-Befehlen zum Anzeigen aller Zweige und zum Zusammenführen von Änderungen. Ein Fehler wird als Merge-Konflikt angezeigt, mit der Anweisung, die Ergebnisse der Konflikte zu beheben und zu committen.
Ein Terminalfenster, das einen Merge-Konflikt in Git anzeigt

Für weitere Informationen kannst du eine git status ausführen und die Details einsehen:

Ein Terminalfenster, das das Ergebnis eines Git-Status-Befehls anzeigt. Es zeigt eine Liste von Dateien in grün mit Anweisungen zum Auflösen von nicht eingebundenen Pfaden.
Ein Terminal-Fenster, das die Ergebnisse eines Git-Status-Befehls anzeigt

Von hier aus kannst du damit beginnen, die verschiedenen Dateien zu bearbeiten, die den Konflikt verursachen. Einige der Werkzeuge und Techniken, die wir im Folgenden besprechen, werden dir dabei helfen.

Abbruch und Zurücksetzen von Zusammenführungen

Manchmal musst du den Merge ganz abbrechen und von vorne anfangen. Die beiden genannten Befehle eignen sich für Situationen, in denen du noch nicht weißt, wie du mit einem Konflikt umgehen sollst.

Mit den folgenden Befehlen kannst du einen laufenden Zusammenführungsprozess abbrechen oder zurücksetzen:

git merge --abort

git reset

Die beiden Befehle sind ähnlich, aber du verwendest sie unter verschiedenen Umständen. Wenn du zum Beispiel einen Merge abbrichst, wird der Zweig einfach auf den Zustand vor dem Zusammenschluss zurückgesetzt. In manchen Fällen funktioniert das aber nicht. Wenn dein Arbeitsverzeichnis zum Beispiel nicht übertragene und nicht gespeicherte Änderungen enthält, kannst du den Abbruch nicht durchführen.

Das Zurücksetzen eines Merge bedeutet jedoch, dass du die Dateien in einen bekannten „guten“ Zustand zurückversetzt. Letzteres solltest du in Betracht ziehen, wenn Git den Merge nicht starten kann. Beachte, dass dieser Befehl alle Änderungen löscht, die du nicht überträgst, was bedeutet, dass dieser Befehl eher eine bewusste Handlung ist, die Vorsicht erfordert.

Überprüfen von Konflikten

Die meisten Konflikte beim Mergen lassen sich leicht feststellen und lösen. In manchen Fällen musst du jedoch tiefer graben, um herauszufinden, warum ein Konflikt auftritt und wie du ihn lösen kannst.

Mit einem Checkout kannst du nach einem git merge mehr Kontext erhalten:

git checkout --conflict=diff3 <filename>

Dabei wird die typische Navigation, die ein Checkout bietet, verwendet und ein Vergleich zwischen den beiden Dateien erstellt, die im Merge-Konflikt angezeigt werden:

Ein Code-Editor, der die Ergebnisse des Befehls git checkout --conflict anzeigt. Er hebt Bereiche des Codes rot hervor und verwendet Symbole, um zu kennzeichnen, wo es eine Änderung gibt, die einen Commit verhindert.
Einen Konflikt innerhalb einer bestimmten Projektdatei überprüfen

Technisch gesehen wird dabei die Datei erneut überprüft und die Konfliktmarkierungen werden ersetzt. Das kannst du im Laufe einer Lösung ein paar Mal machen. Wenn du hier das Argument diff3 angibst, erhältst du die Basisversion und die Alternativen in „ours“ und „theirs“ Versionen.

Beachte, dass das Standardargument merge ist, welches du nicht angeben musst, es sei denn, du änderst den Stil des Zusammenführungskonflikts abweichend vom Standard.

Negative Leerzeichen ignorieren

Negative Leerzeichen und ihre Verwendung sind ein häufiger Diskussionspunkt. Einige Programmiersprachen verwenden unterschiedliche Arten von Abständen und sogar einzelne Entwickler verwenden unterschiedliche Formatierungen.

Leerzeichen und Tabulatoren sind ein Schlachtfeld, an dem wir uns nicht beteiligen werden. Wenn du jedoch Situationen hast, in denen sich die Formatierung je nach Datei und Programmierpraxis ändert, könntest du auf dieses Problem beim Git Merge stoßen.

Wenn du dir den Konflikt ansiehst, erkennst du, dass der Zusammenschluss deshalb fehlgeschlagen ist, weil Zeilen entfernt und hinzugefügt wurden:

Ein Code-Editor, der die Unterschiede zwischen zwei Dateien mit Merge-Konflikten anzeigt. Jeder Bereich, in dem Unterschiede bestehen, wird mit Symbolen gekennzeichnet und rot hervorgehoben.
Eine Datei, die die Konfliktunterschiede in einem Editor zeigt

Das liegt daran, dass Git sich diese Zeilen ansieht und das negative Leerzeichen als eine Änderung ansieht.

Du kannst dem Befehl git merge jedoch bestimmte Argumente hinzufügen, die negative Leerzeichen in den betreffenden Dateien übersehen:

git merge -Xignore-all-space

git merge -Xignore-space-change

Diese beiden Argumente scheinen zwar ähnlich zu sein, aber sie unterscheiden sich deutlich. Wenn du dich dafür entscheidest, alle negativen Leerzeichen zu ignorieren, wird Git dies tun. Das ist zwar ein pauschaler Ansatz, aber im Gegensatz dazu zählt -Xignore-space-change nur Sequenzen mit einem oder mehreren negativen Leerzeichen als gleichwertig. Einzelne Leerzeichen am Ende von Zeilen werden also ignoriert.

Zur zusätzlichen Sicherheit kannst du den Merge auch mit dem Befehl --no-commit überprüfen, um sicherzugehen, dass du negative Leerzeichen richtig ignorierst und zählst.

Logs zusammenführen

Logging ist für fast jede Software, die Daten weitergibt, wichtig. Bei Git kannst du das Protokoll nutzen, um mehr Details über einen Merge-Konflikt zu erfahren. Du kannst diese Informationen über git log abrufen:

Ein Terminalfenster, das das Git-Protokoll für ein Repository anzeigt. Es gibt zwei Commits mit gelber Überschrift sowie Details zu Autor, Datum und Commit-Nachricht.
Ausführen und Anzeigen des Git-Logs im Terminal

Es ist im Wesentlichen eine Textdatei, die jede Aktion innerhalb eines Repos aufzeichnet. Du kannst jedoch weitere Argumente hinzufügen, um die Ansicht zu verfeinern und nur die Commits zu sehen, die du möchtest:

git log --oneline --left-right <branch1>...<branch2>

Hier wird ein „Triple Dot“ verwendet, um eine Liste der Commits zu erstellen, die bei einem Merge in zwei Zweigen involviert sind. Es werden alle Commits herausgefiltert, die beide Zweige gemeinsam haben, so dass eine Auswahl von Commits übrig bleibt, die du weiter untersuchen kannst.

Du kannst auch git log --oneline --left-right --merge verwenden, um nur die Commits auf beiden Seiten eines Merges anzuzeigen, die eine konfliktbehaftete Datei „berühren“. Die Option -p zeigt dir die genauen Änderungen für einen bestimmten „Diff“ an, allerdings nur für Commits, die nicht zusammengeführt wurden. Es gibt eine Umgehungslösung, die wir im Folgenden beschreiben.

Das kombinierte Diff-Format verwenden, um einen Git Merge-Konflikt zu untersuchen

Du kannst die Ansicht, die du mit git log erhältst, weiter nutzen, um Merge-Konflikte zu untersuchen. In der Regel wird Git den Code zusammenführen und alles, was erfolgreich ist, einstellen. Dadurch bleiben nur die konfliktbehafteten Zeilen übrig, die du mit dem Befehl git diff einsehen kannst:

Ein Terminalfenster, das die Ausgabe eines git diff-Befehls anzeigt. Es zeigt Details zu den Änderungen in grünem und rotem Text sowie weitere Details zu den Unterschieden mit Dateinamen innerhalb des Repositorys.
Einen git diff-Befehl im Terminal ausführen

Dieses „kombinierte Diff“-Format fügt zwei zusätzliche Spalten mit Informationen hinzu. Die erste zeigt dir, ob sich eine Zeile zwischen deinem („Ours“-)Zweig und der Arbeitskopie unterscheidet; die zweite gibt dir die gleichen Informationen für den „Theirs“-Zweig.

Ein Pluszeichen bedeutet, dass eine Zeile in der Arbeitskopie hinzugefügt wurde, aber nicht in dieser Seite des Zusammenschlusses, und ein Minuszeichen bedeutet, dass die Zeile entfernt wurde.

Du kannst dieses kombinierte Diff-Format auch im Git-Protokoll sehen, indem du ein paar Befehle verwendest:

git show

git log --cc -p

Der erste ist ein Befehl, den du bei einer Zusammenführungsübergabe verwendest, um deren Verlauf zu sehen. Der zweite Befehl nutzt die Funktionalität von -p, um die Änderungen an einer Nicht-Merge-Commit neben dem kombinierten Diff-Format anzuzeigen.

Wie man einen Git Merge rückgängig macht

Es können Fehler passieren, und du kannst Zusammenführungen durchführen, die du wieder rückgängig machen musst. In manchen Fällen kannst du einfach den letzten Commit mit git commit --amend ändern. Dadurch wird der Editor geöffnet und du kannst die letzte Commit-Nachricht ändern.

Komplexere Merge-Konflikte und die daraus resultierenden Änderungen kannst du zwar rückgängig machen, aber das kann schwierig sein, weil Commits oft dauerhaft sind.

Deshalb musst du eine Reihe von Schritten befolgen:

  • Zuerst musst du Commits überprüfen und Verweise auf die benötigten Merges finden.
  • Als Nächstes checkst du Zweige aus, um die Commit-Historie zu überprüfen.
  • Sobald du die Zweige und Commits kennst, die du brauchst, gibt es spezielle Git-Befehle, die auf deine gewünschte Aktion abgestimmt sind.

Schauen wir uns diese genauer an und beginnen mit dem Review-Prozess. Danach zeigen wir dir, wie du einen Git Merge schnell wieder rückgängig machen kannst, und gehen dann auf spezielle Befehle für fortgeschrittene Anwendungsfälle ein.

Commits überprüfen

Der Befehl git log --oneline ist ideal, wenn du die Revisions-IDs und die Commit-Nachricht für den aktuellen Zweig sehen willst:

Ein Teil eines Terminalfensters, der die Ausgabe eines einzeiligen Git diff-Befehls anzeigt. Er zeigt eine minimale Anzahl von Details an: den Hash des Commits, die Zweige und die Nachricht für jeden, bevor die Terminal-Eingabeaufforderung angezeigt wird.
Einen einzeiligen git diff-Befehl im Terminal ausführen

Der Befehl git log --branches=* zeigt dir die gleichen Informationen, aber für alle Zweige. Unabhängig davon kannst du die Referenz-IDs zusammen mit einem git checkout verwenden, um einen „abgetrennten HEAD“ Status zu erstellen. Das bedeutet, dass du aus technischer Sicht an keinem Zweig arbeitest und sobald du wieder zu einem etablierten Zweig wechselst, „verwaisst“ du die Änderungen.

So kannst du den Checkout fast als risikofreie Sandbox nutzen. Wenn du die Änderungen jedoch beibehalten willst, kannst du den Zweig auschecken und ihm mit git checkout -b <branch-name> einen neuen Namen geben. Das ist eine solide Methode, um eine Git-Zusammenführung rückgängig zu machen, aber für fortgeschrittene Anwendungsfälle gibt es noch weitere Möglichkeiten.

Git Reset verwenden

Viele deiner Merge-Konflikte könnten in einem lokalen Projektarchiv auftreten. In diesen Fällen ist git reset der richtige Befehl für dich. Dieser Befehl hat jedoch mehr Parameter und Argumente, die du beachten musst. Hier erfährst du, wie du den Befehl in der Praxis verwendest:

git reset --hard <reference>

Der erste Teil davon – git reset --hard – durchläuft drei Schritte:

  • Er verschiebt den Referenzzweig an den Ort vor dem Merge-Commit.
  • Durch den Hard-Reset sieht der „Index“ (d.h. der nächste vorgeschlagene Commit-Snapshot) wie der Referenzzweig aus.
  • Er lässt das Arbeitsverzeichnis wie den Index aussehen.

Sobald du diesen Befehl aufrufst, werden spätere Commits aus der Commit-Historie entfernt und die Historie auf die referenzierte ID zurückgesetzt. Das ist eine saubere Methode, um eine Git-Zusammenführung rückgängig zu machen, aber nicht für alle Fälle geeignet.

Du bekommst zum Beispiel einen Fehler, wenn du versuchst, einen lokal zurückgesetzten Commit in ein remotes Repo zu pushen, das diesen Commit enthält. In diesem Fall gibt es einen anderen Befehl, den du verwenden kannst.

Git revert verwenden

Obwohl git reset und git revert ähnlich aussehen, gibt es einige wichtige Unterschiede. In den bisherigen Beispielen geht es beim Rückgängigmachen darum, die Referenzzeiger und den HEAD zu einem bestimmten Commit zu verschieben. Das ist so, als würdest du die Spielkarten mischen, um eine neue Reihenfolge zu erstellen.

Im Gegensatz dazu erstellt git revert einen neuen Commit auf der Grundlage der rückgängig gemachten Änderungen, aktualisiert dann die Referenzzeiger und macht den Zweig zum neuen „Tipp“. Das ist auch der Grund, warum du diesen Befehl bei Konflikten zwischen remoten Repos verwenden solltest.

Du kannst git revert <reference> verwenden, um einen Git-Merge rückgängig zu machen. Beachte, dass du immer eine Commit-Referenz angeben musst, sonst wird der Befehl nicht ausgeführt. Du kannst dem Befehl auch HEAD übergeben, um zum letzten Commit zurückzukehren.

Du kannst Git aber auch mehr Klarheit darüber geben, was du tun willst:

git revert -m 1 <reference>

Wenn du die Zusammenführung aufrufst, hat der neue Commit zwei „Eltern“ Einer bezieht sich auf die von dir angegebene Referenz, der andere ist die Spitze des Zweigs, den du zusammenführen willst. In diesem Fall weist -m 1 Git an, den ersten Elternteil – d.h. die angegebene Referenz – als „Hauptlinie“ zu behalten.

Die Standardoption für git revert ist -e oder --edit. Damit wird der Editor geöffnet, um die Commit-Nachricht zu ändern, bevor du zurückkehrst. Du kannst aber auch --no-edit übergeben, dann wird der Editor nicht geöffnet.

Du kannst auch -n oder --no-commit übergeben. Damit wird git revert angewiesen, keinen neuen Commit zu erstellen, sondern die Änderungen „umzukehren“ und sie dem Staging-Index und dem Arbeitsverzeichnis hinzuzufügen.

Der Unterschied zwischen Merging und Rebasing in Git

Anstelle des Befehls git merge kannst du auch git rebase verwenden. Dies ist ebenfalls eine Möglichkeit, Änderungen in ein Verzeichnis zu integrieren, allerdings mit einem Unterschied:

  • Wenn du git merge verwendest, wird standardmäßig ein Drei-Wege-Merge durchgeführt. Dabei werden Snapshots aus zwei aktuellen Zweigen kombiniert und mit einem gemeinsamen Vorgänger beider Zweige zusammengeführt, um einen neuen Commit zu erstellen.
  • Beim Rebasing wird eine gepatchte Änderung aus einem abweichenden Zweig genommen und auf einen anderen Zweig angewendet, ohne dass der Vorgänger benötigt wird. Das bedeutet, dass es keinen neuen Commit geben wird.

Um diesen Befehl zu verwenden, gehst du zu dem Zweig, den du rebasen möchtest. Von dort aus kannst du den folgenden Befehl verwenden:

git rebase -i <reference>

In vielen Situationen wird deine Referenz dein Hauptzweig sein. Die Option -i startet das „interaktive Rebasing“ Das gibt dir die Möglichkeit, die Commits zu ändern, während sie sich verschieben. Damit kannst du die Commit-Historie aufräumen, was einer der großen Vorteile von git rebase ist.

Wenn du den Befehl ausführst, wird im Editor eine Liste der potenziell zu verschiebenden Commits angezeigt. Damit hast du die Möglichkeit, das Aussehen der Commit-Historie zu verändern. Du kannst auch Commits zusammenführen, wenn du den Befehl pick in fixup änderst.

Sobald du deine Änderungen gespeichert hast, führt Git den Rebase durch. Im Großen und Ganzen verwendest du Git merge für viele Konflikte. Das Rebasen hat aber auch viele Vorteile. Während das Merge-Verfahren zum Beispiel einfach zu bedienen ist und du den Kontext deiner Merge-Historie beibehalten kannst, ist das Rebase-Verfahren sauberer, da du deine Commit-Historie zu einer einzigen zusammenfassen kannst.

Trotzdem musst du beim Rebasing mehr Sorgfalt walten lassen, da die Gefahr von Fehlern groß ist. Außerdem solltest du diese Technik nicht bei öffentlichen Zweigen anwenden, da sich das Rebasing nur auf dein Repo auswirkt. Um die daraus resultierenden Probleme zu beheben, musst du noch mehr Merges durchführen und wirst mehrere Commits sehen.

Tools, die dir helfen, einen Git Merge besser zu verwalten

Angesichts der Komplexität von Git-Merge-Konflikten brauchst du vielleicht eine helfende Hand. Es gibt viele Werkzeuge, die dir helfen, einen erfolgreichen Merge durchzuführen. Wenn du Intellij IDEA verwendest, hast du mit dem Menü Branches eine eingebaute Methode:

Die untere Ecke des Intellij IDEA Code-Editors, die das Git-Widget-Panel zeigt. Das Rechtsklick-Kontextmenü wird angezeigt und hebt die Option Checkout hervor, um Änderungen am Zweig zu überprüfen.
Überprüfen eines Zweigs in Intellij IDEA.

VSCode bietet eine ähnliche Funktion in seiner Benutzeroberfläche (UI). Ältere Atom-Benutzer werden feststellen, dass Microsoft hier seine fantastische Git-Integration fortgesetzt hat, einschließlich der Möglichkeit, sich ohne weitere Erweiterungen oder Add-ons mit GitHub zu verbinden.

Über die Befehlspalette erhältst du außerdem weitere Optionen. Das ist sogar bei Editoren der Fall, die auf dem Open-Source-Framework von VSCode aufbauen, wie z. B. Onivim2:

Ein Teil des Onivim2-Bildschirms zeigt die Befehlspalette und den Befehl Git: Zweig zusammenführen.
Zugriff auf den Befehl Git: Zweig zusammenführen über die Befehlspalette in Onivim2

Der Vorteil ist hier, wie bei allen Tools auf dieser Liste, dass du die Kommandozeile nicht brauchst, um Zusammenführungen durchzuführen. Normalerweise musst du einen Quell- und einen Zielzweig aus einem Dropdown-Menü auswählen und dann den Editor die Zusammenführung durchführen lassen. Trotzdem musst du dich nicht ausklinken. Du kannst die Änderungen nachträglich überprüfen und dann den gewünschten Commit vornehmen.

Ein Editor, der eine eigene grafische Benutzeroberfläche (GUI) für die Arbeit mit Git bietet, ist Sublime Text. Wenn du diesen Editor verwendest, könnte Sublime Merge eine ideale Ergänzung für deinen Arbeitsablauf sein:

Die Submline Merge-Oberfläche zeigt eine Liste der Commits auf der linken Seite des Bildschirms sowie eine Zusammenfassung der Änderungen und Konflikte mit einem bestimmten Commit auf der rechten Seite.
Die Sublime Merge Anwendung

Unabhängig davon, für welchen Code-Editor du dich entscheidest, bietet er oft die Möglichkeit, mit Git zu arbeiten, ohne die Kommandozeile zu benutzen. Das ist sogar bei Vim und Neovim der Fall, wenn du das Git Fugitive Plugin von Tim Pope benutzt, das fantastisch und einfach zu bedienen ist.

Es gibt aber auch ein paar spezielle Merge-Tools von Drittanbietern, die sich ausschließlich auf diese Aufgabe konzentrieren.

Dedizierte Git Merge Anwendungen

Mergify zum Beispiel ist eine unternehmensweite Methode zum Zusammenführen von Code, die in deine Continuous Integration/Continuous Delivery (CI/CD)-Pipeline und deinen Workflow integriert ist:

Ein Bereich der Mergify-Website mit einer Reihe von weiß umrandeten Grafiken auf schwarzem Hintergrund. Es gibt Listen von Git-Zweigen, Timer, Code-Editoren und Diagramme.
Die Mergify Website

Einige der Funktionen hier helfen dir, die Aktualisierung deiner Pull Requests vor dem Merge zu automatisieren, sie nach Priorität neu zu ordnen und sie auch zu stapeln. Für eine Open-Source-Lösung könnte Meld wertvoll sein:

Die Meld-Anwendungs-Oberfläche zeigt den Code nebeneinander an, mit blauer und grüner Markierung, um Änderungen zwischen den einzelnen Dateien zu kennzeichnen.
Die Meld-Anwendungs-Schnittstelle

Die stabile Version unterstützt Windows und Linux und läuft unter der GPL-Lizenz. Sie bietet dir grundlegende Funktionen, um Zweige zu vergleichen, deine Merges zu bearbeiten und mehr. Du bekommst sogar Zwei- oder Drei-Wege-Vergleiche und Unterstützung für andere Versionskontrollsysteme wie Subversion.

Zusammenfassung

Git ist ein unverzichtbares Werkzeug, um zusammenzuarbeiten und Codeänderungen effizient zu verwalten. Wenn jedoch mehrere Entwickler/innen am selben Code arbeiten, kann es zu Konflikten kommen. Git-Merge-Strategien helfen dir, diese Konflikte zu lösen, und es gibt viele Möglichkeiten, diese Aufgabe zu erledigen. Für komplexere Git-Merge-Strategien musst du auf fortgeschrittene Taktiken zurückgreifen.

Das kann so einfach sein wie das Ignorieren negativer Leerzeichen oder das Durchsuchen der Suchprotokolle. Du musst aber auch nicht immer die Kommandozeile benutzen. Es gibt viele Anwendungen, die dir helfen, und auch dein Code-Editor hat oft eine integrierte Schnittstelle.

Wenn du dir ein hochwertiges Anwendungs-Hosting sichern möchtest, sind wir für dich da. Unsere Cloud-basierten Anwendungs-Hosting-Dienste sorgen dafür, dass deine Full-Stack-App im Handumdrehen einsatzbereit ist.

Welche dieser Git-Merge-Strategien hilft dir aus der Patsche? Lass es uns in den Kommentaren unten wissen!

Jeremy Holcombe Kinsta

Content & Marketing Editor bei Kinsta, WordPress Web Developer und Content Writer. Außerhalb von WordPress genieße ich den Strand, Golf und Filme. Außerdem habe ich Probleme mit großen Menschen ;).