Einführung
Wenn Git zwei Änderungen am selben Bereich einer Datei nicht automatisch kombinieren kann, hinterlässt es Konfliktmarker in der Arbeitskopie und lässt Sie manuell auflösen. Die Marker sind keine Magie; sie zeichnen genau auf, was jede Seite relativ zu einer gemeinsamen Basis getan hat.
Anatomie
<<<<<<< HEAD
line as it is on our branch
=======
line as it is on their branch
>>>>>>> feature/login
Der Abschnitt zwischen <<< und === ist "ours" (der aktuelle Branch). Zwischen === und >>> ist "theirs". Auflösen heißt, den richtigen Text zu behalten, die Marker zu löschen und zu stagen.
Three-Way-Marker (diff3-Stil)
git config --global merge.conflictStyle diff3
Nun enthalten die Marker auch die Basisversion:
<<<<<<< HEAD
our version
||||||| merged common ancestor
base version
=======
their version
>>>>>>> feature/login
Die Basis zu sehen klärt oft, was jede Seite beabsichtigte. Noch besser, seit Git 2.35:
git config --global merge.conflictStyle zdiff3
was gemeinsamen Kontext kürzt.
Wie Git sie erzeugt
Für jedes Paar konfliktbehafteter Hunks läuft Git einen Three-Way-Diff zwischen Basis, ours und theirs. Wenn beide Seiten denselben Bereich anders geändert haben, schreibt Git beide Versionen umgeben von Markern. Andernfalls gewinnt die Seite, die geändert hat, automatisch.
Auflösen
git status # konfliktbehaftete Pfade auflisten
jede Datei bearbeiten
git add <file> # als gelöst markieren
git commit # nutzt vorbereitete Nachricht
Oder verwenden Sie ein Merge-Tool:
git mergetool
git config --global merge.tool meld
Jede Seite inspizieren
git show :1:path # Basis
git show :2:path # ours
git show :3:path # theirs
git checkout --ours path
git checkout --theirs path
Die Doppelpunkt-Syntax liest direkt aus den konfliktbehafteten Index-Stages.
Abbrechen
git merge --abort
git rebase --abort
git cherry-pick --abort
rerere
"Reuse recorded resolution" merkt sich Ihre Konfliktauflösungen und wendet sie beim nächsten Auftreten desselben Konflikts erneut an:
git config --global rerere.enabled true
Unverzichtbar für langlebige Rebase-Ketten.
Umbenennungen und Binärkonflikte
Nicht alle Konflikte erzeugen Textmarker. Rename/Rename-, Rename/Delete- und Modify/Delete-Konflikte hinterlassen den Index in einem Zustand mit mehreren Stages, aber ohne <<<-Marker in der Datei. Binärdateien können nicht textuell gemergt werden; beide Versionen werden auf die Festplatte geschrieben und der Index zeichnet den Konflikt auf:
git status
# both modified: image.png
# deleted by us: old.txt
# added by them: new.txt
git checkout --ours image.png # unsere Version behalten
git checkout --theirs new.txt
git add image.png new.txt
Lesen Sie zur Konfliktzeit immer git status; es kennzeichnet diese weniger üblichen Konflikttypen explizit.
Häufige Fehler
Auflösen, indem Sie die Marker löschen, ohne den Inhalt zu lesen, und versehentlich eine Seite weglassen. Lesen Sie immer beide Hälften und die Basis. Vergessen, nach dem Bearbeiten git add auszuführen; git commit verweigert mit "unmerged paths". --ours und --theirs als identisch zu -X ours und -X theirs behandeln; ersteres ersetzt eine ganze konfliktbehaftete Datei, letzteres ist ein Hinweis an die Merge-Strategie. Schließlich: Eine teilweise aufgelöste Datei von woanders kopieren und Git umgehen; der Index hat noch Stage-1/2/3-Einträge, bis Sie git add ausführen.