Beheben eines Git-Konflikts mit Binärdateien

464

Ich habe Git unter Windows (msysgit) verwendet, um Änderungen für einige meiner Designarbeiten zu verfolgen.

Heute habe ich an einem anderen PC gearbeitet (mit Remote Repo brian) und jetzt versuche ich, die heute vorgenommenen Änderungen wieder in meiner regulären lokalen Version auf meinem Laptop zusammenzuführen.

Auf meinem Laptop habe ich git pull brian masterdie Änderungen in meine lokale Version übernommen. Bis auf das InDesign-Hauptdokument war alles in Ordnung - dies zeigt sich als Konflikt.

Die Version auf dem PC ( brian) ist die neueste, die ich behalten möchte, aber ich weiß nicht, welche Befehle das Repo anweisen, diese zu verwenden.

Ich habe versucht, die Datei direkt auf meinen Laptop zu kopieren, aber dies scheint den gesamten Zusammenführungsprozess zu unterbrechen.

Kann mich jemand in die richtige Richtung weisen?

Kevin Wilson
quelle

Antworten:

854

git checkoutakzeptiert eine --oursoder --theirsOption für Fälle wie diesen. Wenn Sie also einen Zusammenführungskonflikt haben und wissen, dass Sie nur die Datei aus dem Zweig möchten, in dem Sie zusammenführen, können Sie Folgendes tun:

$ git checkout --theirs -- path/to/conflicted-file.txt

um diese Version der Datei zu verwenden. Wenn Sie wissen, dass Sie Ihre Version (nicht die, in der sie zusammengeführt wird) möchten, können Sie sie ebenfalls verwenden

$ git checkout --ours -- path/to/conflicted-file.txt
Mipadi
quelle
47
Ich musste 'git reset HEAD path / to / Conflicted-file.txt' für die Datei ausführen, bevor ich --ours verwendete, sonst schien es keine Auswirkung zu haben.
Zitrax
6
@Zitrax Haben Sie die Datei nach dem Ausführen geändert git checkout --ours? Die Manpage schlägt vor (IMHO), dass checkout --ours / - Theirs die Änderung aus der Liste "beide geändert, müssen zusammengeführt werden" entfernt und zum Index hinzufügt, und ich denke, das ist nicht korrekt. Ich glaube, Sie müssen git addnach der Kasse laufen .
Tim Keating
15
Hinweis: Sie möchten weiterhin "git add Conflicted-File.txt " und "Git Commit" ausführen . Als ich es versuchte, war die Festschreibungsnachricht mit einer Notiz über den Konflikt gefüllt.
Edward Falk
2
Die Formulierung von "dem Zweig, in dem Sie zusammenführen" ist gefährlich nahe an "dem Zweig, in den Sie zusammenführen". Ich denke, dass es besser wäre, nur die Präposition zu löschen: "der Zweig, den Sie zusammenführen", was auch den Befehl git widerspiegeln würde (dh git merge branch_name).
Andrybak
13
Ein paar wichtige Punkte, die in den Erklärungen zu diesem Thema immer fehlen. Wenn Sie Rebase anstelle von Merge ausführen, wird die Bedeutung von --theirund --oursvertauscht, dh --their == aktuell ausgecheckter Zweig und --ours ist der Zweig, normalerweise ein Remote-Zweig oder eine Pfadangabe, die Sie in den aktuellen zusammenführen möchten Ast. Die [space]--[space]Option unterscheidet eindeutig von der Pfadspezifikation zwischen dem Zweignamen und der Pfadspezifikation, die beide zufällig mit demselben Namen existieren (z. B. ist ein vorhandener Zweigname "abc" und ein Verzeichnis namens "abc" vorhanden).
BoiseBaked
147

Sie müssen den Konflikt manuell lösen (Kopieren der Datei) und dann die Datei festschreiben (unabhängig davon, ob Sie sie kopiert oder die lokale Version verwendet haben)

git commit -a -m "Fix merge conflict in test.foo"

Git wird normalerweise nach dem Zusammenführen automatisch festgeschrieben. Wenn es jedoch Konflikte erkennt, die es nicht selbst lösen kann, wendet es alle Patches an, die es herausgefunden hat, und überlässt den Rest dem manuellen Auflösen und Festschreiben. Die Git Merge Man Page , der Git-SVN Crash Course oder dieser Blogeintrag geben möglicherweise Aufschluss darüber, wie es funktionieren soll.

Bearbeiten: Siehe den Beitrag unten, Sie müssen die Dateien nicht selbst kopieren, sondern können verwenden

git checkout --ours -- path/to/file.txt
git checkout --theirs -- path/to/file.txt

um die Version der gewünschten Datei auszuwählen. Das Kopieren / Bearbeiten der Datei ist nur erforderlich, wenn Sie beide Versionen mischen möchten.

Bitte markieren Sie die Antwort von mipadis als die richtige.

VolkA
quelle
1
Dank dafür. Ich war mir nicht sicher, ob es eine Art eingebauten Weg gab, eine Datei als die 'richtige' zu markieren. Erklärt, warum ich den nicht vorhandenen Befehl nicht finden konnte!
Kevin Wilson
Ja, das ist ein bisschen unintuitiv - so etwas wie Git Resolution wäre nett, aber auch ein zusätzlicher Schritt ...
VolkA
120

Sie können dieses Problem auch mit überwinden

git mergetool

Dies führt gitdazu, dass lokale Kopien der in Konflikt stehenden Binärdatei erstellt werden und Ihr Standardeditor darauf erscheint:

  • {conflicted}.HEAD
  • {conflicted}
  • {conflicted}.REMOTE

Offensichtlich können Sie Binärdateien in einem Texteditor nicht sinnvoll bearbeiten. Stattdessen kopieren Sie die neue {conflicted}.REMOTEDatei, {conflicted}ohne den Editor zu schließen. Wenn Sie dann schließen git, sieht der Editor , dass die nicht dekorierte Arbeitskopie geändert wurde und Ihr Zusammenführungskonflikt auf die übliche Weise gelöst wird.

RobM
quelle
8
Wenn die Dateien groß sind oder Sie nicht riskieren möchten, Binärdateien in einem Texteditor zu öffnen, können Sie an der Mergetool-Eingabeaufforderung (" Hit return to start merge resolution tool") Strg + C drücken, und Git lässt die zusätzlichen Dateien an Ort und Stelle. Anschließend können Sie sie ändern oder in einem externen Tool zusammenführen (nützlich für binäre Dokumentformate wie LibreOffice / OpenOffice / MSWord) und das Ergebnis unter dem ursprünglichen Dateinamen speichern. Um git darüber zu informieren, dass der Konflikt gelöst ist, geben Sie git addden ursprünglichen Dateinamen ein und Sie können das Zusammenführungs-Commit beenden.
Felix
18

Um das Problem zu beheben, indem Sie die Version in Ihrem aktuellen Zweig behalten (ignorieren Sie die Version aus dem Zweig, in dem Sie zusammenführen), fügen Sie einfach die Datei hinzu und schreiben Sie sie fest:

git commit -a

Um das Problem zu lösen, indem Sie die Version in Ihrem aktuellen Zweig mit der Version aus dem Zweig überschreiben, in dem Sie zusammenführen, müssen Sie diese Version zuerst in Ihr Arbeitsverzeichnis abrufen und dann hinzufügen / festschreiben:

git checkout otherbranch theconflictedfile
git commit -a

Ausführlicher erklärt

Joshua Flanagan
quelle
1
Ich bevorzuge diese Variante gegenüber der akzeptierten Antwort, weil sie intuitiver ist, insbesondere wenn man bedenkt, dass die Bedeutung dieser "--ours" und "--theirs" im Falle einer Umbasierung vertauscht wird.
Antony Hatchkins
11

Mipadis Antwort hat bei mir nicht ganz funktioniert, ich musste das tun:

git checkout - unser Pfad / zu / file.bin

oder, um die zusammengeführte Version beizubehalten:

git checkout - ihr Pfad / zu / file.bin

dann

git add path / to / file.bin

Und dann konnte ich wieder "git mergetool" machen und mit dem nächsten Konflikt fortfahren.

kris
quelle
6

Aus den git checkoutDokumenten

git checkout [-f|--ours|--theirs|-m|--conflict=<style>] [<tree-ish>] [--] <paths>...

--ours
--theirs
Überprüfen Sie beim Auschecken von Pfaden aus dem Index Stufe 2 ( ours) oder 3 ()theirs ) auf nicht zusammengeführte Pfade.

Der Index kann aufgrund einer zuvor fehlgeschlagenen Zusammenführung nicht zusammengeführte Einträge enthalten. Wenn Sie versuchen, einen solchen Eintrag aus dem Index auszuchecken, schlägt der Auscheckvorgang standardmäßig fehl und es wird nichts ausgecheckt. Mit -fwird diese nicht zusammengeführten Einträge ignoriert. Der Inhalt einer bestimmten Seite der Zusammenführung kann mit --oursoder aus dem Index ausgecheckt werden --theirs. Mit -mkönnen Änderungen an der Arbeitsbaumdatei verworfen werden, um das ursprüngliche Ergebnis der Zusammenführung mit Konflikten wiederherzustellen.

user456814
quelle
4

Ich bin auf ein ähnliches Problem gestoßen (ich wollte ein Commit abrufen, das einige Binärdateien enthielt, die beim Zusammenführen Konflikte verursachten), bin aber auf eine andere Lösung gestoßen, die vollständig mit git durchgeführt werden kann (dh Dateien müssen nicht manuell kopiert werden). Ich dachte, ich würde es hier aufnehmen, damit ich mich zumindest daran erinnern kann, wenn ich es das nächste Mal brauche. :) Die Schritte sehen so aus:

% git fetch

Dadurch werden die neuesten Festschreibungen aus dem Remote-Repository abgerufen (je nach Einrichtung müssen Sie möglicherweise einen Namen für die Remote-Verzweigung angeben), es wird jedoch nicht versucht, diese zusammenzuführen. Es zeichnet das Commit in FETCH_HEAD auf

% git checkout FETCH_HEAD stuff/to/update

Dies nimmt die Kopie der gewünschten Binärdateien und überschreibt den Inhalt des Arbeitsbaums mit der Version, die aus dem Remote-Zweig abgerufen wurde. git versucht nicht, eine Zusammenführung durchzuführen, sodass Sie am Ende nur eine exakte Kopie der Binärdatei aus dem Remote-Zweig erhalten. Sobald dies erledigt ist, können Sie die neue Kopie wie gewohnt hinzufügen / festschreiben.

Brian Webster
quelle
4

Mit diesem Verfahren werden Konflikte mit Binärdateien gelöst, nachdem Sie eine Pull-Anforderung an Github gesendet haben:

  1. Bei Github haben Sie also festgestellt, dass Ihre Pull-Anfrage einen Konflikt mit einer Binärdatei aufweist.
  2. Kehren Sie nun zu demselben Git-Zweig auf Ihrem lokalen Computer zurück.
  3. Sie (a) erstellen / erstellen diese Binärdatei erneut und (b) übergeben die resultierende Binärdatei an denselben Git-Zweig.
  4. Dann schiebst du denselben Git-Zweig erneut zu Github.

Auf Github sollte der Konflikt auf Ihre Pull-Anfrage hin verschwinden.

David M Lee
quelle
Dies ist genau das Verfahren, das ich brauche
Huifang Feng
2

Wenn die Binärdatei mehr als eine DLL ist oder direkt bearbeitet werden kann wie ein Bild oder eine Mischdatei kann (und Sie die eine oder andere Datei nicht in den Papierkorb werfen / auswählen müssen), wäre eine echte Zusammenführung wie folgt:

Ich schlage vor, nach einem Diff-Tool zu suchen, das sich an Ihrer Binärdatei orientiert. Beispielsweise gibt es einige kostenlose Tools für Bilddateien

und vergleiche sie.

Wenn es kein Diff-Tool zum Vergleichen Ihrer Dateien gibt, haben Sie den Originalgenerator der Bin-Datei (dh es gibt einen Editor dafür ... wie bei Blender 3d können Sie diese Dateien auch manuell überprüfen Sehen Sie sich die Protokolle an und fragen Sie die andere Person, was Sie einschließen sollten. Führen Sie eine Ausgabe der Dateien mit https://git-scm.com/book/es/v2/Git-Tools-Advanced-Merging#_manual_remerge aus

$ git show :1:hello.blend > hello.common.blend $ git show :2:hello.blend > hello.ours.blend $ git show :3:hello.blend > hello.theirs.blend

tyoc213
quelle
1

Ich bin auf zwei Strategien gestoßen, um das Diff / Merge von Binärdateien mit Git unter Windows zu verwalten.

  1. Mit Tortoise Git können Sie Diff / Merge-Tools für verschiedene Dateitypen basierend auf ihren Dateierweiterungen konfigurieren. Siehe 2.35.4.3. Erweiterte Diff / Merge-Einstellungen http://tortoisegit.org/docs/tortoisegit/tgit-dug-settings.html . Diese Strategie setzt natürlich voraus, dass geeignete Diff / Merge-Tools verfügbar sind.

  2. Mithilfe von Git-Attributen können Sie ein Tool / einen Befehl angeben, um Ihre Binärdatei in Text zu konvertieren, und dann Ihr Standard-Diff / Merge-Tool ausführen lassen. Siehe http://git-scm.com/book/it/v2/Customizing-Git-Git-Attributes . Der Artikel enthält sogar ein Beispiel für die Verwendung von Metadaten, um Bilder zu unterscheiden.

Ich habe beide Strategien, um mit Binärdateien von Softwaremodellen zu arbeiten, aber wir haben uns für Tortoise Git entschieden, da die Konfiguration einfach war.

BoJohDoh
quelle
0

Ich verwende Git Workflow für Excel - https://www.xltrail.com/blog/git-workflow-for-excel , um die meisten Probleme beim Zusammenführen von Binärdateien zu beheben. Diese Open-Source-App hilft mir, Probleme produktiv zu lösen, ohne zu viel Zeit zu investieren, und lässt mich ohne Verwirrung die richtige Version der Datei auswählen.

Siddhartha Thota
quelle
0

Mein Fall scheint ein Fehler zu sein ... mit Git 2.21.0

Ich habe einen Pull gemacht ... es hat sich über Binärdateien beschwert:

warning: Cannot merge binary files: <path>
Auto-merging <path>
CONFLICT (content): Merge conflict in <path>
Automatic merge failed; fix conflicts and then commit the result.

Und dann führte nichts in einer der Antworten hier zu einer Ausgabe, die irgendeinen Sinn ergab.

Wenn ich mir anschaue, welche Datei ich jetzt habe ... ist es die, die ich bearbeitet habe. Wenn ich es auch tue:

git checkout --theirs -- <path>
git checkout --ours -- <path>

Ich bekomme Ausgabe:

Updated 0 paths from the index

und ich habe immer noch meine Version der Datei. Wenn ich rm und dann auschecke, wird stattdessen 1 angezeigt, aber es gibt mir immer noch meine Version der Datei.

Git Mergetool sagt

No files need merging

und Git Status sagt

    All conflicts fixed but you are still merging.
    (use "git commit" to conclude merge)

Eine Möglichkeit besteht darin, das Commit rückgängig zu machen ... aber ich hatte Pech und hatte viele Commits, und dieses schlechte war das erste. Ich möchte keine Zeit damit verschwenden, das zu wiederholen.

um diesen Wahnsinn zu lösen:

Ich bin gerade gelaufen

git commit

Das verliert die Remote-Version und verschwendet wahrscheinlich etwas Speicherplatz für eine zusätzliche Binärdatei ... dann

git checkout <commit where the remote version exists> <path>

Das gibt mir die Remote-Version zurück

dann die Datei erneut bearbeitet ... und dann festschreiben und pushen, was wiederum wahrscheinlich bedeutet, Speicherplatz mit einer anderen Kopie der Binärdatei zu verschwenden.

Peter
quelle
In meinem Fall git checkout --ours <path>habe ich nach dem Versuch erhalten Updated 0 paths from the index . Ich habe das mit git add <path>Befehl behoben , der das gleiche tut.
Andriy