Wählen Sie die Git-Zusammenführungsstrategie für bestimmte Dateien ("unsere", "meine", "ihre").

207

Ich bin gerade dabei, nach a git pull --rebase. Ich habe einige Dateien mit Zusammenführungskonflikten. Wie kann ich "ihre" Änderungen oder "meine" Änderungen für bestimmte Dateien akzeptieren?

$ git status
# Not currently on any branch.
# You are currently rebasing.
#   (fix conflicts and then run "git rebase --continue")
#   (use "git rebase --skip" to skip this patch)
#   (use "git rebase --abort" to check out the original branch)
#
# Changes to be committed:
#   (use "git reset HEAD <file>..." to unstage)
#
#       modified:  CorrectlyMergedFile
#
# Unmerged paths:
#   (use "git reset HEAD <file>..." to unstage)
#   (use "git add <file>..." to mark resolution)
#
#       both modified: FileWhereIWantToAcceptTheirChanges
#       both modified: FileWhereIWantToAcceptMyChanges

Normalerweise öffne ich einfach die Datei oder ein Zusammenführungstool und akzeptiere manuell alle "ihre" oder "meine" Änderungen. Ich vermute jedoch, dass mir ein praktischer Git-Befehl fehlt.

Beachten Sie außerdem, dass ich nur dann eine Zusammenführungsstrategie für jede Datei auswählen kann, wenn ich sehe, welche Dateien Konflikte treffen und möglicherweise welche Konflikte auftreten.

Steven Wexler
quelle
@AbeVoelker Ich glaube nicht, dass das mein Problem löst. Ich möchte eine Zusammenführungsstrategie für bestimmte Dateien auswählen. Beachten Sie außerdem, dass ich nur weiß, welche Zusammenführungsstrategie zu verwenden ist, wenn ich mich in meiner Rebase befinde, und sehe, welche Dateien Konflikte getroffen haben und welche Konflikte auftreten.
Steven Wexler
Ich habe diese Frage allgemeiner bearbeitet: stackoverflow.com/questions/278081/… . Vielleicht können wir diese Frage als Duplikat davon schließen? Ist das angemessen?
@ TheShadow Das scheint mir vernünftig.
Steven Wexler
Ich war mir nicht sicher, ob es angemessen war, den Titel der anderen Frage in das zu ändern , was ich getan habe, da ich den Teil über das Auflösen von Binärdateien herausgenommen habe. Ich habe die andere Frage auf den vorherigen Stand zurückgesetzt, sodass diese aktuelle Frage immer noch einen Mehrwert bietet.

Antworten:

251

Für jede Konfliktdatei, die Sie erhalten, können Sie angeben

git checkout --ours -- <paths>
# or
git checkout --theirs -- <paths>

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 von 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 Konfliktzusammenführung wiederherzustellen.


quelle
9
Ist es möglich, ihre für alle Dateien zu akzeptieren, die umergiert bleiben?
Aslakjo
41
@aslakjo git rebase -s recursive -X <ours/theirs>oder git merge -s recursive -X <ours/theirs>. Denken Sie daran, dass für eine Rebase "unsere" und "ihre" umgekehrt sind wie bei einer Zusammenführung. Sie könnten wahrscheinlich auch nur einen Datei- / Shell-Glob verwenden, wie z git checkout --theirs -- *.txt.
2
Vielen Dank, @Cupcake, die unerwartete Umkehrung ours/theirsmit Rebase hat mich verrückt gemacht !! (Es macht jetzt Sinn, dass ich darüber nachdenke, wie eine Rebase tatsächlich funktioniert, aber überhaupt nicht intuitiv.)
Dan Lenski
2
@DanLenski Rebase im Allgemeinen ist nur ein wirklich schwieriges Werkzeug, das die Leute zunächst verstehen können. Wenn Sie jedoch erst einmal verstanden haben, wie es funktioniert, können Sie alle möglichen wirklich mächtigen Dinge damit tun.
1
@ VincentSels eigentlich müssen Sie das * -Zeichen maskieren, sonst versucht die Shell, es zu erweitern. Also wird in Ihrem Fall git checkout --outs -- "**/*.csproj"das tun, was Sie meinen. Gleiches gilt zB für git lfs track "*.jpg". Wenn Sie einige JPG-Dateien in Ihrem CWD haben, ohne die Anführungszeichen, werden nur diese verfolgt.
eFloh
117

Auch wenn diese Frage beantwortet wird, geben Sie ein Beispiel dafür, was "ihre" und "unsere" im Fall von Git Rebase vs Merge bedeuten. Siehe diesen Link

Git Rebase
theirs ist im Falle von Rebase der aktuelle Zweig . Die folgenden Befehle akzeptieren also tatsächlich Ihre aktuellen Zweigänderungen über den Remote-Zweig.

# see current branch
$ git branch
... 
* branch-a
# rebase preferring current branch changes during conflicts
$ git rebase -X theirs branch-b

Git Merge
Beim Zusammenführen wird die Bedeutung von theirsund oursumgekehrt. Um den gleichen Effekt während einer Zusammenführung zu erzielen , behalten Sie Ihre aktuellen Zweigänderungen ( ours) über dem zusammengeführten Remote-Zweig ( theirs) bei.

# assuming branch-a is our current version
$ git merge -X ours branch-b  # <- ours: branch-a, theirs: branch-b
Abe
quelle
2
Nun, das ist eine ziemlich wichtige Unterscheidung! Danke fürs klarstellen.
Verboze
26

Beachten Sie, dass git checkout --ours|--theirswerden die Dateien vollständig überschreiben , indem Sie entweder theirsoder oursVersion, die möglicherweise oder möglicherweise nicht , was Sie tun wollen (wenn Sie nicht-Konflikt Änderungen haben von der anderen Seite kommen, werden sie verloren).

Wenn Sie stattdessen einen Drei-Wege - Merge auf die Datei ausführen möchten, und lösen nur die konflikt große Stücke mit --ours|--theirs, während halten nicht-Konflikt große Stücke von beiden Seiten an Ort und Stelle ist , sollten Sie greifen auf git merge-file; Details finden Sie in dieser Antwort .

jakub.g
quelle
1
In Bezug auf "nicht widersprüchliche Änderungen", die verloren gehen - bezieht sich dies nur auf die Dateien, in denen nicht widersprüchliche Änderungen in bestimmten Zeilen vorhanden sind, ansonsten in derselben Datei, oder auf alle Änderungen aus allen Dateien in ausgerichteten Historien?
Ktamlyn
2
@ktamlyn mit "nicht widersprüchliche Änderungen" meine ich Änderungen in der gleichen Datei. Zum Beispiel gibt es example.txtin der oursVersion zwei geänderte Hunks (Teile) , eines ist in Konflikt geraten (auch in der theirsRevision geändert ), das andere ist nicht in Konflikt geraten. Wenn Sie dies tun git checkout --theirs example.txt, wird bei der theirsÜberarbeitung nur blind die gesamte Datei gelesen , und der nicht konfliktreiche Teil des Diff geht verloren.
Jakub.g
1
Vielen Dank! Dies war für mich eine notwendige Klarstellung, obwohl "Änderungen in derselben Datei" in diesem Zusammenhang am sinnvollsten sind.
Ktamlyn
Dies sollte die akzeptierte Antwort sein, obwohl sie nicht wirklich eine Antwort gibt, sondern auf ein wichtiges Problem in der anderen vorgeschlagenen Lösung hinweist.
Tomasyany
1
Wenn Sie zur ursprünglichen Datei mit Konflikten zurückkehren möchten, können Sie diese ausführen git checkout --merge <path>.
Andrew Keeton