So beheben Sie Merge-Konflikte in Git – Tutorial

Was ist ein Git-Merge-Konflikt?

Das Git-Versionierungssystem dreht sich darum, als Team zu arbeiten und zu Projekten beizutragen. Entwickler arbeiten normalerweise an isolierten Branches, und wenn sie fertig sind, führen sie die Änderungen mit der Hauptbranche zusammen. Diese Art der Teamarbeit ist sehr produktiv und effektiv beim Finden von Fehlern. Manchmal arbeiten mehrere Entwickler an derselben Codezeile, und wenn sie versuchen, die Änderungen zusammenzuführen, entstehen Konflikte. 


Einfaches Beispiel für einen Git-Konflikt

Das obige Diagramm gibt ein perfektes Beispiel dafür, wie ein typischer Git-Merge-Konflikt entsteht. Der Hauptzweig enthält eine Datei mit dem Text „HELLO, WORLD!“. Der Benutzername abid forkt den Hauptzweig und ändert den Text in „HELLO, CAT!“. Während abid Änderungen vornimmt, wird der ursprüngliche Hauptzweig auch geändert in „HELLO, DOG!“. Das Zusammenführen dieser Zweige löst einen Merge-Konflikt aus und stoppt den Prozess.  

Der Befehl `git merge` hat primär die Aufgabe, zwei Zweige zu kombinieren und die Konflikte automatisch zu lösen. Gelegentlich treten jedoch Konflikte auf, bei denen zwei Personen die gleiche Codezeile geändert haben oder kritische Dateien entfernt haben, an denen ein anderer Entwickler gearbeitet hat. Git markiert diese Änderungen und stoppt den Merge-Prozess. In diesem Fall wurden die Konflikte nicht automatisch gelöst; stattdessen muss der Entwickler manuelle Änderungen vornehmen oder Werkzeuge verwenden, um den Konflikt zu lösen.

Merge-Typen

Git merge und rebase sind zwei Wege, um Commits von einem Zielzweig in einen Quellzweig zu integrieren. Darüber hinaus führt Git merge entweder einen Fast-Forward- oder einen No-Fast-Forward-Merge durch. Wenn der Kopf des Zielzweigs im Quellzweig existiert, ist der Standardmerge-Typ ein Fast-Forward-Merge und wenn er fehlt, ein No-Fast-Forward-Merge. Git rebase ist ein anderer Merge-Typ, der die Commit-Geschichte des Zielzweigs neu ordnet. 

Fast-forward Merge

Standardmäßig verwendet Git Merge Fast-Forward, um fehlende Commits in den Zielzweig zu integrieren. Zum Beispiel wird es verwendet, um den lokalen Zweig von einem Remote-Server mit dem Pull-Befehl zu aktualisieren. Fast-Forward löst keine Merge-Konfliktprobleme aus, da Git es nicht anwendet, wenn der Kopf des Zielzweigs im Quellzweig fehlt.

No-fast-forward Merge

Ein No-fast-forward Merge wird auch als dreiseitiger oder echter Merge bezeichnet. Er erzeugt einen neuen Commit auf einem Zielzweig, indem Änderungen sowohl im Quellzweig als auch im Zielzweig integriert werden. Die Änderungen werden nach dem letzten gemeinsamen Commit in beiden Zweigen gemischt. In unserem Fall ist es nach dem C. Bei diesem Merge-Typ wird ein Git-Merge-Konflikt ausgelöst, wenn der Quellzweig mit dem Zielzweig im Konflikt steht. Im obigen Diagramm wird der Merge-Commit (X) durch die Integration von Quell- und Zielzweig erzeugt, wobei K und E die Eltern des Merge-Commits sind.

Rebase

Git rebase ist etwas anders als andere Typen. Es ändert die Sequenz der Commit-Geschichte des Zielzweigs. Rebase integriert den Quellzweig so, dass der Zielzweig alle Änderungen vom Quellzweig enthält, gefolgt von allen Commits des Zielzweigs nach dem letzten gemeinsamen Commit. In unserem Fall ist der letzte gemeinsame Commit der C, während D und E vom Quellzweig stammen. Der K*-Commit ist der gleiche wie K, aber mit einer anderen Commit-ID. Statt C zu verlinken, wird er E verlinken. Wie bei einem No-fast-forward Merge wird Git, falls es Kompatibilitätsprobleme zwischen Quell- und Zielzweig gibt, ein Problem auslösen, um Konflikte zu lösen, bevor das Rebase abgeschlossen wird.

Arten von Git Merge Konflikten

Es gibt zwei Arten von Git-Merge-Konflikten: zu Beginn und während des Zusammenführungsprozesses – Atlassian. In diesem Abschnitt werden wir beide Arten und die Wege zur Lösung jedes Szenarios kennenlernen. 

Zu Beginn der Zusammenführung

Git-Merge schlägt zu Beginn fehl, wenn es Änderungen im Arbeitsverzeichnis oder im Staging-Bereich gibt. Es schlägt zu Beginn fehl, um zu verhindern, dass die Änderungen durch eingehende Merge-Commits überschrieben werden. Dies geschieht aufgrund von Konflikten mit lokalen Änderungen, nicht mit anderen Branches oder Entwicklern. Um den lokalen Zustand zu stabilisieren, können Sie Befehle wie git stash, git commit, git checkout oder git reset verwenden.

Während der Zusammenführung

Ein Fehler während der Zusammenführung bedeutet, dass es einen Konflikt zwischen dem Quell- und dem Ziel-Branch gibt, bei dem mehrere Entwickler dieselbe Datei geändert haben. Wenn die automatische Zusammenführung fehlschlägt, wird Git Sie auffordern, die Probleme manuell zu lösen. Sie können auch Drittanbieter-Tools verwenden, um Ihnen bei der Visualisierung und Integration der Änderungen zu helfen.

Befehle zur Lösung von Git-Merge-Konflikten

In diesem Abschnitt werden wir verschiedene native Befehle kennenlernen, um die Git-Merge-Konflikte zu visualisieren und zu lösen. 

Häufige Befehle

Git status ist der am häufigsten verwendete Befehl, um den Status von geänderten Dateien, dem Staging-Bereich und den Commits anzuzeigen. Während des Zusammenführungsprozesses wird er verwendet, um Konfliktdateien zu identifizieren.

git status

Der Git-Log mit den –merge-Argumenten erzeugt die Liste der Commits, die im Konflikt mit der Quellbranch sind.

git log --merge

Standardmäßig zeigt die git diff-Option die Differenzen zwischen unveröffentlichten Änderungen und vorherigen Commits an. Git diff wird verwendet, um branches, Commits und Dateien zu vergleichen. Es ist nützlich für die Vermeidung zukünftiger Merge-Konflikte.

git diff

Befehle für Merge-Fehler am Anfang

Der checkout-Befehl wird verwendet, um Änderungen rückgängig zu machen oder zu einer neuen oder alten Branch zu wechseln.

git checkout

Der Git-Reset ist dafür gedacht, Änderungen im Arbeitsverzeichnis und im Commit-Bereich zurückzukehren.

git reset --mixed

Befehle für Konflikte während des Merges

Das –abort-Argument stoppt den Merge-Prozess und kehrt die Änderungen in ihren ursprünglichen Zustand vor dem Beginn des Merges zurück.

git merge --abort

Git reset wird normalerweise während des Merge-Prozesses verwendet, um conflictierten Dateien ihren ursprünglichen Zustand zurückzukehren.

git reset

Lösen von Konflikten zwischen gelöschten und geänderten Dateien

Ein Git-Konflikt tritt auf, wenn Sie die Datei in Ihrem aktuellen Branch gelöscht und jemand anderer sie in einem anderen Branch verändert hat. In diesem Fall können Sie entweder eine Datei hinzufügen und Commit tun,

git add <filename>

oder Sie können die Datei entfernen und Commit tun.

git rm <filename>

Visuelle Merge-Tools

Integrierte Mergetools sind grafische, benutzerfreundliche Programme, die zur Erkennung und Lösung aller Arten von Merge-Konflikten verwendet werden können. Einige der Tools bieten zusätzliche Fähigkeiten, wie beispielsweise die Vergleich von Änderungen, Git-Operationen und die Verwaltung von Projekten und Repositories. Es gibt zwei Arten von Git-Mergetools: die nur im Terminal funktionierenden und die grafisch orientierten. Die terminalbasierten Tools öffnen innerhalb von PowerShell oder Bash, während die grafisch orientierten Tools in einer Fensterumgebung öffnen.

Um die Liste der installierten und gültigen Tools zu prüfen, verwendet man:

git mergetool --tool-help

Diese Liste umfasst alle gültigen Tools, die installiert und mit Git-Befehlen integriert werden können.

Zum Beispiel werden vim und nvim standardmäßig installiert, und wenn man die Differenzen zwischen einem unveröffentlichten Datei und einem vorherigen Commit sehen möchte, tippt man:

git difftool --tool=vimdiff3

Die vimdiff3-Tools zeigt die Änderungen und ermöglicht es, Commits im Terminal zu vergleichen.

Unterschied zwischen zwei Versionen derselben Datei in Vimdiff3

Meld

Meld ist ein kostenloser und quelloffener Tool, das die Lösung von Merge-Konflikten auf ein neues Niveau bringt. Um es mit Git zu integrieren, muss man zunächst die Setupdatei vom offiziellen Server herunterladen und installieren. Anschließend sollte man es zur globalen Konfiguration hinzufügen, sodass Git standardmäßig Meld zum Lösen von Konflikten startet.

Die untenstehenden Konfigurationsbefehle gelten nur für Windows-Benutzer. Die einzige Änderung, die du machen musst, besteht darin, den Pfad der installierten Meld-Datei für Mac oder Linux zu ändern.

git config --global merge.tool meld git config --global mergetool.meld.path "C:/Program Files (x86)/Meld/Meld.exe" git config --global diff.tool meld git config --global difftool.meld.path "C:/Program Files (x86)/Meld/Meld.exe"

Nach der Einrichtung der Standardeinstellungen können Sie innerhalb des lokalen Git-Verzeichnisses git difftool eingeben, um die Windows-Version von Meld zu starten, oder Sie können git mergetool verwenden, um Merge-Konflikte wie unten gezeigt zu lösen.

Beilegen eines Merge-Konflikts mit Meld

VSCode

VSCode bietet die beste und beliebteste Methode zum Beilegen von Merge-Konflikten. Wenn Git Dateien nicht automatisch zusammenführen kann, hebt VSCode den kollidierenden Code hervor und bietet Ihnen vier Optionen: aktuelle Änderungen übernehmen, eingehende Änderungen übernehmen, beide Änderungen übernehmen und Änderungen vergleichen. Mit diesen Optionen können Sie Ihre Datei bereinigen und alle ausstehenden Probleme lösen. 

Beilegen von Merge-Konflikten mit VSCode

Wenn Sie nach einer vollständigen Lösung für Ihre Git-Operationen suchen, probieren Sie GitKraken. Es kommt mit einem kostenlosen Client, einer VSCode-Erweiterung und bietet ein integriertes Tool zum Beilegen von Merge-Konflikten.  

Wie man einen Git-Merge-Konflikt löst

In diesem Abschnitt werden wir erfahren, wie ein Git-Fachvermerk entsteht und wie er gelöst wird. Der Leitfaden ist in zwei Teile aufgeteilt. Der erste Teil behandelt die lokale Lösung von Git-Konflikten, der zweite Teil beschäftigt sich mit der Lösung von Konflikten mit einem Remote-Server (GitHub).

Lokaler Merge-Konflikt

Durch die Erstellung von Merge-Konflikten können wir erfahren, wie diese Probleme am Ursprung entstanden sind. Wir können dann kreative Möglichkeiten zur Lösung dieser Probleme nutzen oder sie gar vermeiden.

Nun werden wir ein Git-Repository mit einer einzigen Datei erstellen und unser erstes Commit vornehmen, um zu beginnen.

  1. Erstellen Sie ein Verzeichnis mit dem Namen datacamp.
  2. Wechseln Sie in das Verzeichnis datacamp.
  3. Initialisieren Sie Git.
  4. Erstellen Sie eine README.md-Datei mit dem angegebenen Titel.
  5. Fügen Sie den Änderungen in einer Datei einen Commit hinzu.
mkdir datacamp cd datacamp git init echo "# How to Resolve Git Merge Conflict" > README.md git add README.md git commit -m "first commit" >>> [main (root-commit) 8199ea2] first commit >>> 1 file changed, 1 insertion(+) >>> create mode 100644 README.md

Nächstes werden wir eine neue Branch namens readme erstellen und den Titel von “..Git Merge..” in “..Git..” ändern. Fügen Sie die Datei hinzu und erstellen Sie den Commit mit dem -am Argument.

git checkout -b readme echo "# How to Resolve Git Conflict" > README.md git commit -am "new branch conflict added" >>> [readme 155f694] new branch conflict added >>> 1 file changed, 1 insertion(+), 1 deletion(-)

Gehen Sie zur Hauptbranch zurück und fügen Sie einer README.md-Datei eine neue Zeile mit >> hinzu. Durch Speichern der Änderungen und Erstellen von Commits haben wir erfolgreich einen Konflikt zwischen zwei Versionen derselben Datei erstellt.

git checkout main echo "New change in base branch" >> README.md git commit -am " a line added to base branch Readme file" >>> [main f1f1874] a line added to base branch Readme file >>> 1 file changed, 1 insertion(+)

Wie wir sehen können, hat Git beim Mergen der readme-Branch einen Hinweis ausgegeben, dass die automatische Fusion fehlgeschlagen ist und wir die Änderungen manuell vornehmen und dann den Ergebnis-Commit abschließen müssen.

git merge readme >>> Auto-merging README.md >>> CONFLICT (content): Merge conflict in README.md >>> Automatic merge failed; fix conflicts and then commit the result.

Wir werden das Problem manuell lösen, indem wir die Datei im Notepad öffnen und bearbeiten. Das Bild unten zeigt einen Pfeil mit HEAD, einen Trennstrich und einen anderen Pfeil mit einer readme. Der HEAD-Teil zeigt die bestehenden Änderungen im Hauptzweig, und der readme-Teil ist der Zweig, der uns interessiert, da er aus einer anderen Überschrift besteht.

Manuelle Lösung eines Merge-Konflikts

Um das Problem zu lösen, entfernen wir den Teil der readme-Zweig, die Pfeile und den Trennstrich. Die endgültige Version der Datei sollte sauber aussehen, wie unten gezeigt.

Konflikt gelöst

Nachdem wir die Datei hinzugefügt und einen Commit erstellt haben, ist der Merge-Konflikt gelöst. Dies ist der allgemeine und einfachste Weg, um Probleme zu lösen. Sie können auch eine integrierte Entwicklungsumgebung (IDE) verwenden, um Probleme schneller zu lösen.

git commit -am "conflict resolved in file README.md" >>> [main 9994a29] conflict resolved in file README.md

Remote Merge Conflict

um Merge-Konflikte am entfernten Repository zu lösen, müssen wir ein neues Repository auf GitHub erstellen.

Erstellen eines neuen Repositories auf GitHub

Fügen Sie dem Repository den Remote-Namen (origin) mit der Adresse hinzu und pushen Sie alle Änderungen aus dem lokalen Repository in den Remote-Hauptzweig mithilfe von upstream.

git remote add origin https://github.com/kingabzpro/DataCamp-Git-Merge-Guide.git git push --set-upstream origin main >>> Enumerating objects: 12, done. >>> Counting objects: 100% (12/12), done. >>> Delta compression using up to 4 threads >>> Compressing objects: 100% (6/6), done. >>> Writing objects: 100% (12/12), 998 bytes | 499.00 KiB/s, done. >>> Total 12 (delta 2), reused 0 (delta 0), pack-reused 0 >>> remote: Resolving deltas: 100% (2/2), done. >>> To https://github.com/kingabzpro/DataCamp-Git-Merge-Guide.git >>> * [new branch] main -> main >>> branch 'main' set up to track 'origin/main'.

Um einen Konflikt zu erzeugen, müssen wir Änderungen im Remote- und lokalen README.md-Datei vornehmen. Sie können den GitHub-Dateieditor verwenden, um „..Git merge..“ in „..Sit-Merge..“ zu ändern und die Änderungen dann zu committen. 

Änderungen im GitHub-Editor vornehmen

Im lokalen Repository ändern Sie anschließend die README.md-Datei nur so, dass Sie einen einfachen Titel hinzufügen und die Änderungen commiten. 

echo "# How to Resolve Merge Conflicts in Git Tutorial" > README.md git commit -am "local branch changes in README.md" >>> [main c677a13] local branch changes in README.md >>> 1 file changed, 1 insertion(+), 4 deletions(-)

Pushen Sie schließlich die Änderungen auf den Remote-Server. Beachten Sie, dass Git einen Fehler meldet und Hinweise gibt, wie das Problem gelöst werden kann. 

git push >>> To https://github.com/kingabzpro/DataCamp-Git-Merge-Guide.git >>> ! [rejected] main -> main (fetch first) >>> error: failed to push some refs to 'https://github.com/kingabzpro/DataCamp-Git-Merge-Guide.git' >>> hint: Updates were rejected because the remote contains work that you do >>> hint: not have locally. This is usually caused by another repository pushing >>> hint: to the same ref. You may want to first integrate the remote changes >>> hint: (e.g., 'git pull ...') before pushing again. >>> hint: See the 'Note about fast-forwards' in 'git push --help' for details.

Wir werden dem einfachsten Hinweis folgen, das heißt, die Datei vom Remote-Server zu pullen, bevor wir pushen. 

Das Pull der Datei scheitert aufgrund eines Merge-Konflikts in der README.md-Datei. Wir könnten dies manuell mit Notepad beheben, aber dieses Mal werden wir ein visuelles Tool verwenden, um uns in diesem Prozess zu assistieren. 

git pull >>> remote: Enumerating objects: 5, done. >>> remote: Counting objects: 100% (5/5), done. >>> remote: Compressing objects: 100% (2/2), done. >>> remote: Total 3 (delta 0), reused 0 (delta 0), pack-reused 0 >>> Unpacking objects: 100% (3/3), 681 bytes | 75.00 KiB/s, done. >>> From https://github.com/kingabzpro/DataCamp-Git-Merge-Guide >>> aaf149d..49b7d14 main -> origin/main >>> Auto-merging README.md >>> CONFLICT (content): Merge conflict in README.md >>> Automatic merge failed; fix conflicts and then commit the result.

Das Merge-Tool Meld wird Konfliktdateien erkennen und in der Meld-GUI-Anwendung anzeigen.   

git mergetool >>> Merging: >>> README.md >>> Normal merge conflict for 'README.md': >>> {local}: modified file >>> {remote}: modified file

Es gibt drei Spalten: README_LOCAL_473.md, README.md und README_LOCAL_473.md. Wenn Sie denken, dass die Remote-Änderungen gültig sind, klicken Sie auf den schwarzen Pfeil in der Remote-Spalte; und wenn Sie möchten, dass lokale Änderungen bestehen bleiben, klicken Sie auf den schwarzen Pfeil in der lokalen Spalte. Es ist so einfach. 

Konflikt mit Mergetool Meld gelöst

Nach den Änderungen sollte die Datei gespeichert und committed werden. Wie du siehst, erkennt das Pushen einer Datei auf einen Remote-Server keinen Merge-Konflikt.

git commit -am "remote main branch conflict resolved" git push >>> Enumerating objects: 16, done. >>> Counting objects: 100% (16/16), done. >>> Delta compression using up to 4 threads >>> Compressing objects: 100% (6/6), done. >>> Writing objects: 100% (10/10), 1.08 KiB | 550.00 KiB/s, done. >>> Total 10 (delta 2), reused 0 (delta 0), pack-reused 0 >>> remote: Resolving deltas: 100% (2/2), completed with 1 local object. >>> To https://github.com/kingabzpro/DataCamp-Git-Merge-Guide.git >>> 49b7d14..8f5c3aa main -> main

Wir haben sowohl lokale als auch remote Merge-Konflikte erfolgreich gelöst. Diese Konflikte werden täglich von Datenwissenschaftlern und Maschinelles Lernen Ingenieuren behandelt. Um deine Fähigkeiten in Git-Operationen zu verbessern, kannst du einen Git-Einführungskurs belegen.

Schlussfolgerung

Die Lösung von Git-Merge-Konflikten ist eine komplizierte und hoch riskante Aufgabe, da du Software zerstören kannst, indem du fehlerhafte Code integriert. Merge-Tools bieten ein benutzerfreundliches Umfeld mit einer sichereren Methode zur Erkennung und Lösung von Merge-Konflikten. In diesem Tutorial haben wir erkannt, warum Git-Konflikte auftreten und wie sie gelöst werden. Wir haben auch verschiedene Merge- und Konfliktarten, nützliche Git-Befehle und visuelle Tools behandelt. Im letzten Abschnitt haben wir einen Merge-Konflikt in einem lokalen und Remote-Repository erstellt und gelöst.

Wenn du neu bei Git bist und lernen willst, wie es funktioniert, dann lies: Git und GitHub-Einführungstutorial.

Source:
https://www.datacamp.com/tutorial/how-to-resolve-merge-conflicts-in-git-tutorial