Git Merge-Konflikte
Versionskontrollsysteme werden verwendet, um Beiträge von mehreren verteilten Autoren (in der Regel Entwickler) zu verwalten. Manchmal kann es vorkommen, dass mehrere Entwickler versuchen, denselben Inhalt zu bearbeiten. Wenn Entwickler A Code bearbeiten möchte, an dem Entwickler B gerade arbeitet, kann es zu einem Konflikt kommen. Um das Auftreten von Konflikten zu vermeiden, arbeiten Entwickler in voneinander getrennten isolierten Branches. Mit dem Befehl git merge
werden in erster Linie separate Branches kombiniert und eventuell bestehende Bearbeitungskonflikte behoben.
Grundlegendes zu Merge-Konflikten
Konflikte entstehen in der Regel dann, wenn zwei Personen dieselben Zeilen in einer Datei geändert haben oder ein Entwickler eine Datei löscht, während ein anderer Entwickler diese ändert. In diesen Fällen kann Git nicht automatisch entscheiden, welcher Vorgang richtig ist. Die Konflikte betreffen nur den Entwickler, der den Merge durchführt – der Rest des Teams bemerkt von dem Konflikt nichts. Git kennzeichnet die betreffende Datei als "in Konflikt stehend" und stoppt den Merge-Vorgang. Es ist dann Aufgabe des Entwicklers, den Konflikt zu lösen.
Arten von Merge-Konflikten
Bei einem Merge können an zwei separaten Stellen Konflikte entstehen: zu Beginn und während des Merge-Vorgangs. Im Folgenden sprechen wir darüber, wie jedes dieser Konfliktszenarien behandelt werden kann.
Git kann Merge nicht starten
Der Start eines Merge-Vorgangs schlägt fehl, wenn Git erkennt, dass Änderungen entweder im Arbeitsverzeichnis oder im Staging-Bereich des aktuellen Projekts vorgenommen wurden. Git führt den Merge nicht aus, weil diese ausstehenden Änderungen durch die Commits überschrieben werden könnten, die gemergt werden. Wenn dies geschieht, liegt das nicht an Konflikten mit anderen Entwicklern, sondern an Konflikten mit ausstehenden lokalen Änderungen. Der lokale Status muss mithilfe der Befehle git stash
, git checkout
, git commit
oder git reset
stabilisiert werden. Ein Merge-Fehler beim Start gibt die folgende Fehlermeldung aus:
error: Entry '<fileName>' not uptodate. Cannot merge. (Changes in working directory)
Bei Git tritt während dem Merge-Vorgang ein Fehler auf
Ein Fehler WÄHREND eines Merge-Vorgangs weist auf einen Konflikt zwischen dem aktuellen lokalen Branch und dem Branch hin, der gerade gemergt wird. Dies wiederum bedeutet einen Konflikt mit dem Code eines anderen Entwicklers. Git wird alles versuchen, um die Dateien zu mergen, überlässt dir aber die Aufgabe, Probleme mit in Konflikt stehenden Dateien manuell zu beheben. Bei einem Fehler während des Merge-Vorgangs wird die folgende Fehlermeldung ausgegeben:
Zugehöriges Material
Git-Protokoll für Fortgeschrittene
Lösung anzeigen
Git kennenlernen mit Bitbucket Cloud
error: Entry '<fileName>' would be overwritten by merge. Cannot merge. (Changes in staging area)
Erstellen eines Merge-Konflikts
Damit du mit Merge-Konflikten vertrauter wirst, wird im nächsten Abschnitt ein Konflikt simuliert, der später untersucht und gelöst werden soll. Für das Beispiel wird eine Unix-ähnliche Git-CLI (Command Line Interface) verwendet, über die diese Simulation ausgeführt wird.
$ mkdir git-merge-test
$ cd git-merge-test
$ git init .
$ echo "this is some content to mess with" > merge.txt
$ git add merge.txt
$ git commit -am"we are commiting the inital content"
[main (root-commit) d48e74c] we are commiting the inital content
1 file changed, 1 insertion(+)
create mode 100644 merge.txt
Dieses Codebeispiel führt eine Reihe von Befehlen aus, mit denen Folgendes erreicht wird:
- Erstelle ein neues Verzeichnis namens
git-merge-test,
wechsle zu diesem Verzeichnis und initialisiere es als neues Git-Repository. - Erstelle eine neue Textdatei
merge.txt
mit einigen Inhalten. - Füge
merge.txt
zum Repository hinzu und committe die Datei.
Jetzt ist ein neues Repository mit einem main
-Branch und einer Datei namens merge.txt
mit Inhalten entstanden. Als Nächstes erstellen wir einen neuen Branch, der für einen in Konflikt stehenden Merge-Vorgang verwendet werden soll.
$ git checkout -b new_branch_to_merge_later
$ echo "totally different content to merge later" > merge.txt
$ git commit -am"edited the content of merge.txt to cause a conflict"
[new_branch_to_merge_later 6282319] edited the content of merge.txt to cause a conflict
1 file changed, 1 insertion(+), 1 deletion(-)
Die nachstehende Befehlsreihenfolge bewirkt Folgendes:
- Du erstellst einen neuen Branch namens
new_branch_to_merge_later
und checkst ihn aus. - Du überschreibst den Inhalt in
merge.txt
. - Du committest den neuen Inhalt.
Mit diesem neuen Branch new_branch_to_merge_later
haben wir einen Commit erstellt, der die Inhalte von merge.txt
überschreibt.
git checkout main
Switched to branch 'main'
echo "content to append" >> merge.txt
git commit -am"appended content to merge.txt"
[main 24fbe3c] appended content to merge.tx
1 file changed, 1 insertion(+)
Mithilfe dieser Befehlskette wird der main
-Branch ausgecheckt, der Datei merge.txt
Inhalt hinzugefügt und dieser dann committet. Mit diesem Schritt werden aus unserem Beispiel-Repository zwei neue Commits: einer im main
-Branch und einer im Branch namens new_branch_to_merge_later
. An dieser Stelle lassen wir Git new_branch_to_merge_later
mergen und beobachten, was passiert.
$ git merge new_branch_to_merge_later
Auto-merging merge.txt
CONFLICT (content): Merge conflict in merge.txt
Automatic merge failed; fix conflicts and then commit the result.
BUMM 💥. Es ist ein Konflikt aufgetreten. Danke für den Hinweis, Git!
Identifizierung von Merge-Konflikten
Wie wir aus dem vorangehenden Beispiel gelernt haben, erstellt Git einen beschreibenden Text, der uns über das Auftreten eines KONFLIKTS informiert. Detailliertere Informationen dazu erhalten wir durch die Ausführung des Befehls git status.
$ git status
On branch main
You have unmerged paths.
(fix conflicts and run "git commit")
(use "git merge --abort" to abort the merge)
Unmerged paths:
(use "git add <file>..." to mark resolution)
both modified: merge.txt
Die Ausgabe von git status
weist darauf hin, dass der Konflikt zu nicht gemergten Pfaden geführt hat. Die Datei merge.text
wird jetzt im Status "modifiziert" angezeigt. Sehen wir uns die Datei an, um herauszufinden, was geändert wurde.
$ cat merge.txt
<<<<<<< HEAD
this is some content to mess with
content to append
=======
totally different content to merge later
>>>>>>> new_branch_to_merge_later
Hier haben wir den Befehl cat
verwendet, um die Inhalte der Datei merge.txt
hervorzuheben, und können feststellen, dass seltsame neue Ergänzungen gemacht wurden:
<<<<<<< HEAD
=======
>>>>>>> new_branch_to_merge_later
Betrachte diese neuen Zeilen als "Konflikt-Trennlinien". Die Zeile =======
ist das "Zentrum" des Konflikts. Alle Inhalte zwischen der Mitte und der Zeile <<<<<<< HEAD
sind Inhalte, die im aktuellen Haupt-Branch vorhanden sind, auf den die HEAD
-Referenz verweist. Hingegen ist alles, was zwischen der Mitte und >>>>>>> new_branch_to_merge_later
liegt, Inhalt, der in unserem zu mergenden Branch vorliegt.
Behebung von Merge-Konflikten mithilfe der Befehlszeile
Der direkteste Weg, um Merge-Konflikte zu beheben, ist die Bearbeitung der in Konflikt stehenden Datei. Öffne hierzu die Datei merge.txt
im Editor deiner Wahl. Bei unserem Beispiel hier entfernen wir einfach alle problematischen Trennlinien. Der geänderte Inhalt in merge.txt
sollte wie folgt aussehen:
this is some content to mess with
content to append
totally different content to merge later
Sobald du die Datei bearbeitet hast, kannst du mit git add merge.txt
den neu gemergten Inhalt stagen. Zum Abschluss des Merge-Vorgangs erstellst du einen neuen Commit, indem du folgenden Befehl ausführst:
git commit -m "merged and resolved the conflict in merge.txt"
Git erkennt, dass der Konflikt behoben wurde, und erstellt einen neuen Merge-Commit, um den Vorgang abzuschließen.
Git-Befehle für die Behebung von Merge-Konflikten
Allgemeine Tools
git status
Der status-Befehl wird für die Arbeit mit Git häufig verwendet und während eines Merge-Vorgangs können damit in Konflikt stehende Dateien identifiziert werden.
git log --merge
Durch die Übergabe des Arguments --merge
an den git log
-Befehl wird ein Protokoll mit einer Liste an Commits erstellt, die zwischen mergenden Branches für Konflikte sorgen.
git diff
Mithilfe von diff
lassen sich Unterschiede zwischen Status von Repositorys/Dateien einfacher auffinden, was für die Prognose und Vermeidung von Merge-Konflikten nützlich ist.
Tools für den Fall, wenn Git keinen Merge-Vorgang starten kann
git checkout
Der Befehl checkout
kann verwendet werden, um Änderungen in Dateien rückgängig zu machen oder um Branches zu wechseln.
git reset --mixed
reset
wird genutzt, um Änderungen am Arbeitsverzeichnis und am Staging-Bereich zu widerrufen.
Tools für den Fall, wenn während eines Merge-Vorgangs Git-Konflikte entstehen
git merge --abort
Durch die Ausführung des Befehls git merge
mit der Option --abort
kannst du den Merge-Prozess verlassen und den Branch auf den Status vor dem Merge zurücksetzen.
git reset
Git reset
kann während eines Merge-Konflikts verwendet werden, um in Konflikt stehende Dateien auf einen als funktionierend bekannten Status zurückzusetzen.
Zusammenfassung
Merge-Konflikte können eine ziemliche Wirkung haben. Zum Glück bietet Git leistungsstarke Tools, um Konflikten aus dem Weg zu gehen oder sie zu lösen. Git kann die meisten Merge-Vorgänge dank automatischer Merging-Features selbst handhaben. Ein Konflikt entsteht, wenn in zwei separaten Branches Bearbeitungen derselben Zeile in einer Datei vorgenommen wurden oder wenn eine Datei in einem Branch gelöscht, aber in einem anderen bearbeitet wurde. Konflikte entstehen am häufigsten bei der Arbeit in einer Teamumgebung.
Es gibt zahlreiche Tools, um Merge-Konflikte zu lösen. Git verfügt über genügend Befehlszeilentools, die hier besprochen wurden. Weitere detaillierte Informationen zu diesen Tools findest du auf den jeweiligen Seiten zu git log, git reset, git status, git checkout und git reset. Neben Git bieten viele Tools von Drittanbietern optimierte Supportfunktionen für Merge-Konflikte an.
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.