5329 Stimmen

Wie löse ich Zusammenführungskonflikte in einem Git-Repository?

Ich möchte Zusammenführungskonflikte in meinem Git-Repository auflösen.

Wie kann ich das tun?

40 Stimmen

Der folgende Blog-Beitrag enthält ein sehr gutes Beispiel für den Umgang mit Merge-Konflikten mit Git, das Sie auf den richtigen Weg bringen sollte. Umgang mit und Vermeidung von Konflikten in Git

4 Stimmen

Sie können ein Zusammenführungswerkzeug konfigurieren (kdiff3 jebaird.com/2013/07/08/… ) und verwenden Sie dann git mergetool. Wenn Sie in großen Entwicklerteams arbeiten, werden Sie immer wieder auf Merge-Konflikte stoßen.

0 Stimmen

Vergessen Sie nicht, dass Sie die meisten Merge-Konflikte durch regelmäßiges Merging Downstream entschärfen können!

3362voto

Peter Burns Punkte 43323

Versuchen Sie es: git mergetool

Es öffnet eine grafische Benutzeroberfläche, die Sie durch die einzelnen Konflikte führt, und Sie können wählen, wie sie zusammengeführt werden sollen. Manchmal muss man danach noch etwas von Hand nachbearbeiten, aber in der Regel reicht das schon aus. Es ist auf jeden Fall viel besser als die ganze Sache von Hand zu machen.

Gemäß Josh Glover's Kommentar :

Der Befehl

öffnet nicht unbedingt eine grafische Benutzeroberfläche, es sei denn, Sie installieren eine. Ausführen von git mergetool ergab sich für mich vimdiff verwendet werden. Sie können eines der folgenden Tools installieren, um es stattdessen zu verwenden: meld , opendiff , kdiff3 , tkdiff , xxdiff , tortoisemerge , gvimdiff , diffuse , ecmerge , p4merge , araxis , vimdiff , emerge .

Nachfolgend finden Sie ein Beispiel für ein Verfahren, das Sie verwenden können vimdiff um Zusammenführungskonflikte zu lösen. Basierend auf dieser Link

Schritt 1 : Führen Sie folgende Befehle in Ihrem Terminal aus

git config merge.tool vimdiff
git config merge.conflictstyle diff3
git config mergetool.prompt false

Dadurch wird vimdiff als Standard-Zusammenführungswerkzeug festgelegt.

Schritt 2 : Führen Sie folgenden Befehl im Terminal aus

git mergetool

Schritt 3 : Sie werden eine vimdiff-Anzeige im folgenden Format sehen

   LOCAL  BASE  REMOTE 

          MERGED         

Diese 4 Ansichten sind

LOCAL - dies ist eine Datei aus dem aktuellen Zweig

BASE - gemeinsamer Vorgänger, wie die Datei vor beiden Änderungen aussah

REMOTE - Datei, die Sie in Ihren Zweig einbinden

MERGED - Ergebnis der Zusammenführung, dies wird im Repo gespeichert

Sie können zwischen diesen Ansichten navigieren, indem Sie ctrl + w . Sie können die MERGED-Ansicht direkt über ctrl + w gefolgt von j .

Weitere Informationen über die vimdiff-Navigation sind aquí et aquí .

Schritt 4 . Sie können die MERGED-Ansicht auf folgende Weise bearbeiten

Wenn Sie Änderungen von REMOTE erhalten möchten

:diffg RE

Wenn Sie Änderungen von BASE erhalten möchten

:diffg BA

Wenn Sie Änderungen von LOCAL erhalten möchten

:diffg LO

Schritt 5 . Speichern, Beenden, Bestätigen und Aufräumen

:wqa Speichern und Beenden von vi

git commit -m "message"

git clean Entfernen Sie zusätzliche Dateien (z.B. *.orig), die vom Diff-Tool erstellt wurden.

58 Stimmen

Zu Ihrer Information: Sie können verwenden git mergetool -y um ein paar Tastenanschläge zu sparen, wenn Sie viele Dateien auf einmal zusammenführen.

394 Stimmen

Nun, es wird nicht unbedingt eine grafische Benutzeroberfläche geöffnet, es sei denn, Sie installieren eine. Ausführen von git mergetool ergab sich für mich vimdiff verwendet werden. Sie können eines der folgenden Tools installieren, um es stattdessen zu verwenden: meld opendiff kdiff3 tkdiff xxdiff tortoisemerge gvimdiff diffuse ecmerge p4merge araxis vimdiff emerge .

31 Stimmen

Gutes Argument, Josh. Auf Ubuntu hatte ich das beste Glück mit meld, seine Drei-Wege-Merge-Anzeige ist nicht schlecht. Auf OSX wählte Git einen schönen Standard.

1788voto

coolaj86 Punkte 69032

Hier ist ein wahrscheinlicher Anwendungsfall, von oben:

Sie werden einige Änderungen vornehmen, aber ups, Sie sind nicht auf dem neuesten Stand:

git fetch origin
git pull origin master

From ssh://gitosis@example.com:22/projectname
 * branch            master     -> FETCH_HEAD
Updating a030c3a..ee25213
error: Entry 'filename.c' not uptodate. Cannot merge.

Sie werden also auf den neuesten Stand gebracht und versuchen es erneut, haben aber einen Konflikt:

git add filename.c
git commit -m "made some wild and crazy changes"
git pull origin master

From ssh://gitosis@example.com:22/projectname
 * branch            master     -> FETCH_HEAD
Auto-merging filename.c
CONFLICT (content): Merge conflict in filename.c
Automatic merge failed; fix conflicts and then commit the result.

Also beschließen Sie, sich die Änderungen anzusehen:

git mergetool

Oh je, oh je, im Vorfeld wurden einige Dinge geändert, aber nur um meine Änderungen zu verwenden...nein...ihre Änderungen...

git checkout --ours filename.c
git checkout --theirs filename.c
git add filename.c
git commit -m "using theirs"

Und dann versuchen wir ein letztes Mal

git pull origin master

From ssh://gitosis@example.com:22/projectname
 * branch            master     -> FETCH_HEAD
Already up-to-date.

Ta-da!

21 Stimmen

Das war sehr hilfreich, denn ich hatte viele Fehler bei der Zusammenführung von Binärdateien (Art-Assets) und die Zusammenführung scheint immer zu scheitern, also muss ich sie immer mit der neuen Datei überschreiben und nicht "zusammenführen".

2 Stimmen

Das war genau das, wonach ich gesucht habe! Warum, oh warum, kann "git checkout -- filename.c" nicht auch hier funktionieren Das wäre zu konsequent, denke ich.

206 Stimmen

Vorsichtig! Die Bedeutung von --ours und --theirs ist umgekehrt. --ours == die Ferne. --theirs == das Lokale. Siehe git merge --help

780voto

Mark E. Haase Punkte 24620

Ich finde, dass mir Merge-Tools selten helfen, den Konflikt oder die Lösung zu verstehen. Normalerweise bin ich erfolgreicher, wenn ich mir die Konfliktmarkierungen in einem Texteditor ansehe und das Git-Protokoll als Ergänzung verwende.

Hier sind ein paar Tipps:

Tipp Eins

Ich habe festgestellt, dass es am besten ist, den Stil "diff3" für Zusammenführungskonflikte zu verwenden:

git config merge.conflictstyle diff3

Dies führt zu solchen Konfliktmarkierungen:

<<<<<<<
Changes made on the branch that is being merged into. In most cases,
this is the branch that I have currently checked out (i.e. HEAD).
|||||||
The common ancestor version.
=======
Changes made on the branch that is being merged in. This is often a 
feature/topic branch.
>>>>>>>

Der mittlere Abschnitt zeigt, wie der gemeinsame Vorfahre aussah. Dies ist nützlich, weil Sie ihn mit der oberen und unteren Version vergleichen können, um ein besseres Gefühl dafür zu bekommen, was auf jedem Zweig geändert wurde, was Ihnen eine bessere Vorstellung davon vermittelt, was der Zweck jeder Änderung war.

Handelt es sich um einen Konflikt, der nur wenige Zeilen umfasst, wird der Konflikt dadurch in der Regel sehr deutlich. (Zu wissen, wie man einen Konflikt löst, ist etwas ganz anderes; man muss wissen, woran andere Leute arbeiten. Wenn Sie verwirrt sind, ist es wahrscheinlich am besten, die betreffende Person in Ihr Zimmer zu rufen, damit sie sehen kann, was Sie gerade sehen.)

Wenn der Konflikt länger ist, schneide ich jeden der drei Abschnitte aus und füge ihn in drei separate Dateien ein, z. B. "meine", "gemeinsame" und "ihre".

Dann kann ich die folgenden Befehle ausführen, um die beiden diff hunks zu sehen, die den Konflikt verursacht haben:

diff common mine
diff common theirs

Dies ist nicht dasselbe wie die Verwendung eines Zusammenführungswerkzeugs, da ein Zusammenführungswerkzeug auch alle nicht widersprüchlichen Diff-Hunks einschließt. Das empfinde ich als störend.

Tipp zwei

Jemand hat es bereits erwähnt, aber die Intention hinter jedem Unterschied zu verstehen, ist im Allgemeinen sehr hilfreich, um zu verstehen, woher ein Konflikt kommt und wie man damit umgehen kann.

git log --merge -p <name of file>

Dies zeigt alle Commits an, die diese Datei zwischen dem gemeinsamen Vorgänger und den beiden Köpfen, die Sie zusammenführen, berührt haben. (Es schließt also keine Commits ein, die bereits vor dem Zusammenführen in beiden Zweigen vorhanden waren.) Dies hilft Ihnen, Diff Hunks zu ignorieren, die eindeutig kein Faktor in Ihrem aktuellen Konflikt sind.

Tipp Drei

Überprüfen Sie Ihre Änderungen mit automatisierten Tools.

Wenn Sie automatisierte Tests haben, führen Sie diese durch. Wenn Sie eine Fussel , führen Sie das aus. Wenn es sich um ein kompilierbares Projekt handelt, bauen Sie es, bevor Sie es übertragen, usw. In allen Fällen müssen Sie ein paar Tests durchführen, um sicherzustellen, dass Ihre Änderungen nichts kaputt machen. (Sogar ein Merge ohne Konflikte kann funktionierenden Code zerstören).

Tipp Vier

Planen Sie im Voraus; kommunizieren Sie mit Ihren Mitarbeitern.

Wenn Sie im Voraus planen und wissen, woran andere arbeiten, können Sie Konflikte vermeiden und/oder früher lösen - solange die Details noch frisch im Gedächtnis sind.

Wenn Sie z.B. wissen, dass Sie und eine andere Person an verschiedenen Refactoring-Projekten arbeiten, die beide dieselben Dateien betreffen, sollten Sie vorher miteinander sprechen, um ein besseres Gefühl dafür zu bekommen, welche Art von Änderungen jeder von Ihnen vornimmt. Sie können viel Zeit und Mühe sparen, wenn Sie Ihre geplanten Änderungen nacheinander und nicht parallel durchführen.

Bei größeren Refactorings, die einen großen Teil des Codes betreffen, sollten Sie unbedingt in Erwägung ziehen, seriell zu arbeiten: Jeder stellt die Arbeit an diesem Bereich des Codes ein, während eine Person das komplette Refactoring durchführt.

Wenn Sie nicht seriell arbeiten können (z. B. aufgrund von Zeitdruck), dann hilft Ihnen die Kommunikation über zu erwartende Konflikte bei der Zusammenführung zumindest, die Probleme früher zu lösen, solange die Details noch frisch im Gedächtnis sind. Wenn zum Beispiel ein Kollege eine störende Reihe von Übertragungen über einen Zeitraum von einer Woche macht, können Sie sich dafür entscheiden, den Zweig dieses Kollegen ein- oder zweimal pro Tag während dieser Woche zusammenzuführen/zu rebasen. Auf diese Weise können Sie, wenn Sie Merge/Rebase Konflikte finden, diese schneller lösen, als wenn Sie ein paar Wochen warten, um alles in einem großen Klumpen zusammenzuführen.

Tipp Fünf

Wenn Sie sich bei einer Verschmelzung unsicher sind, sollten Sie sie nicht erzwingen.

Das Zusammenführen von Dateien kann sich sehr anstrengend anfühlen, vor allem, wenn es viele widersprüchliche Dateien gibt und die Konfliktmarkierungen Hunderte von Zeilen umfassen. Bei der Kalkulation von Software-Projekten wird oft nicht genügend Zeit für Overhead-Elemente wie die Bearbeitung eines komplizierten Mergers eingeplant, so dass es sich wie eine echte Qual anfühlt, mehrere Stunden mit dem Sezieren jedes Konflikts zu verbringen.

Langfristig gesehen sind eine vorausschauende Planung und die Kenntnis dessen, woran andere arbeiten, die besten Mittel, um sich auf entstehende Konflikte einzustellen und sich darauf vorzubereiten, sie in kürzerer Zeit korrekt zu lösen.

8 Stimmen

Die Option diff3 ist eine großartige Funktion für Zusammenführungen. Die einzige GUI, die mir begegnet ist, die sie anzeigt, ist die von Perforce p4merge das separat von den anderen Perforce-Tools installiert und verwendet werden kann (die ich nicht benutzt habe, über die ich aber Beschwerden gehört habe).

4 Stimmen

Nach einem Rebase-Versuch, der zu einem Merge-Konflikt führte: $ git log --merge -p build.xml output: fatal: --merge without MERGE_HEAD?

0 Stimmen

git config merge.conflictstyle diff3 - Ich danke Ihnen, Sir. Dies ist erstaunlich und hat mich von dem Versuch befreit, eine gute 3-Wege-Zusammenführungs-GUI zu finden (und $$ zu bezahlen). IMO ist dies besser, weil es den gemeinsamen Vorfahren sowie lokal/entfernt zeigt, y zeigt die letzten Commit-Log-Zeilen an, was (AFAIK) keine GUI kann. Die Commits helfen Ihnen auf jeden Fall zu erkennen, welcher Code zu welchem Zweig gehört.

369voto

davetron5000 Punkte 22918
  1. Stellen Sie fest, welche Dateien in Konflikt stehen (Git sollte Ihnen das sagen).

  2. Öffnen Sie jede Datei und prüfen Sie die Diffs; Git grenzt sie ab. Hoffentlich ist es offensichtlich, welche Version eines jeden Blocks Sie behalten sollten. Möglicherweise müssen Sie dies mit anderen Entwicklern besprechen, die den Code übertragen haben.

  3. Sobald Sie den Konflikt in einer Datei aufgelöst haben git add the_file .

  4. Sobald Sie eine Lösung gefunden haben todo Konflikte, tun git rebase --continue oder welcher Befehl auch immer Git sagte, was Sie tun sollten, als Sie fertig waren.

39 Stimmen

@Justin Betrachten Sie Git als Tracking Inhalt anstatt Dateien zu verfolgen. Dann ist es einfach zu sehen, dass der Inhalt, den Sie aktualisiert haben ist nicht im Repository und muss hinzugefügt werden. Diese Denkweise erklärt auch, warum Git leere Ordner nicht verfolgt: Obwohl es sich technisch gesehen um Dateien handelt, gibt es keinen Inhalt zu verfolgen.

7 Stimmen

Inhalt vorhanden ist, tritt ein Konflikt auf, weil es 2 Versionen des Inhalts gibt. Daher klingt "git add" nicht korrekt. Und es funktioniert nicht (git add, git commit), wenn Sie nur diese eine Datei übertragen wollen, nachdem der Konflikt gelöst wurde ("fatal: cannot do a partial commit during a merge.")

1 Stimmen

Ja, technisch gesehen ist dies eine Antwort auf die gestellte Frage, aber meiner Meinung nach keine brauchbare Antwort, sorry. Was ist die Punkt einen Zweig mit einem anderen gleichzusetzen? Natürlich wird eine Zusammenführung Konflikte verursachen

125voto

kenorb Punkte 134883

Zusammenführungskonflikte entstehen, wenn an einer Datei gleichzeitig Änderungen vorgenommen werden. Hier ist, wie man sie löst.

git CLI

Hier sind einfache Schritte, was zu tun ist, wenn man in einen Konflikt gerät:

  1. Beachten Sie die Liste der konfliktbehafteten Dateien mit: git status (unter Unmerged paths Abschnitt).

  2. Lösen Sie die Konflikte separat für jede Datei auf eine der folgenden Arten:

    • Verwenden Sie GUI, um die Konflikte zu lösen: git mergetool (der einfachste Weg).

    • Um eine entfernte/andere Version zu akzeptieren, verwenden Sie: git checkout --theirs path/file . Dadurch werden alle lokalen Änderungen, die Sie für diese Datei vorgenommen haben, verworfen.

    • Um die lokale/unsere Version zu akzeptieren, verwenden Sie: git checkout --ours path/file

      Sie müssen jedoch vorsichtig sein, da aus irgendeinem Grund entfernte Änderungen vorgenommen wurden, die Konflikte verursachen.

      Verwandt: Was ist die genaue Bedeutung von "unser" und "ihr" in Git?

    • Bearbeiten Sie die konfliktbehafteten Dateien manuell und suchen Sie den Codeblock zwischen <<<<< / >>>>> dann wählen Sie die Version entweder von oben oder von unten ===== . Siehe: Wie Konflikte dargestellt werden .

    • Pfad- und Dateinamenkonflikte können gelöst werden durch git add / git rm .

  3. Überprüfen Sie schließlich die Dateien, die für die Übergabe bereit sind: git status .

    Wenn Sie noch Dateien unter Unmerged paths und Sie den Konflikt manuell gelöst haben, dann lassen Sie Git wissen, dass Sie ihn gelöst haben, indem Sie: git add path/file .

  4. Wenn alle Konflikte erfolgreich gelöst wurden, übertragen Sie die Änderungen durch: git commit -a und drücken Sie wie gewohnt auf die Fernbedienung.

Siehe auch: Auflösen eines Zusammenführungskonflikts über die Befehlszeile auf GitHub

Eine praktische Anleitung finden Sie hier: Szenario 5 - Behebung von Konflikten bei der Zusammenführung durch Katacoda .

DiffMerge

Ich habe erfolgreich eingesetzt DiffMerge das Dateien unter Windows, macOS und Linux/Unix visuell vergleichen und zusammenführen kann.

Es kann die Änderungen zwischen 3 Dateien grafisch darstellen und ermöglicht das automatische Zusammenführen (wenn es sicher ist) und die volle Kontrolle über die Bearbeitung der resultierenden Datei.

DiffMerge

Bildquelle: DiffMerge (Linux-Bildschirmausschnitt)

Laden Sie es einfach herunter und führen Sie es im Repo als aus:

git mergetool -t diffmerge .

macOS

Unter macOS können Sie über installieren:

brew install caskroom/cask/brew-cask
brew cask install diffmerge

Und wahrscheinlich (falls nicht vorhanden) müssen Sie den folgenden einfachen Wrapper in Ihrem PATH platzieren (z.B. /usr/bin ):

#!/bin/sh
DIFFMERGE_PATH=/Applications/DiffMerge.app
DIFFMERGE_EXE=${DIFFMERGE_PATH}/Contents/MacOS/DiffMerge
exec ${DIFFMERGE_EXE} --nosplash "$@"

Dann können Sie die folgenden Tastenkombinationen verwenden:

  • - Alt - Up / Down um zu vorherigen/nächsten Änderungen zu springen.
  • - Alt - Left / Right Wechselgeld von links oder rechts zu akzeptieren

Alternativ können Sie auch opendiff (Teil der Xcode Tools), mit dem Sie zwei Dateien oder Verzeichnisse zusammenführen können, um eine dritte Datei oder ein drittes Verzeichnis zu erstellen.

CodeJaeger.com

CodeJaeger ist eine Gemeinschaft für Programmierer, die täglich Hilfe erhalten..
Wir haben viele Inhalte, und Sie können auch Ihre eigenen Fragen stellen oder die Fragen anderer Leute lösen.

Powered by:

X