Lösen Sie Git-Zusammenführungskonflikte zugunsten ihrer Änderungen während eines Pulls

1226

Wie löse ich einen Git-Merge-Konflikt zugunsten gezogener Änderungen?

Grundsätzlich muss ich alle widersprüchlichen Änderungen aus einem Arbeitsbaum entfernen, ohne alle Konflikte mit einer git mergetoolWeile durchlaufen zu müssen, während alle konfliktfreien Änderungen beibehalten werden. Tun Sie dies vorzugsweise beim Ziehen, nicht danach.

Sanmai
quelle
3
mögliches Duplikat von git merge -s unser, was ist mit "ihrem"
2
Duplikat von Git Pull von der Fernbedienung. Kann ich es zwingen, Konflikte zu überschreiben, anstatt sie zu melden? Sie können dort die gleiche Lösung sehen.
Dan Dascalescu
3
@DanDascalescu Akzeptierte Antwort dort beantwortet diese Fragen nicht, es handelt sich also eindeutig nicht um ein Duplikat. Außerdem ist diese andere Frage ziemlich zweideutig: Es ist sehr schwer zu sagen, was gestellt wird. Alles in allem kann ich Ihnen nicht zustimmen. Was meinst du damit?
Sanmai
2
@sanmai Du hast zwei Antworten - und du hast eine davon akzeptiert. Können Sie besser erklären, was Sie in einer Antwort erwarten und wie viel mehr Details Sie hier wünschen?
Edward Thomson
2
@ EdwardThomson gut, eigentlich habe ich darüber nachgedacht, diesen Ruf für die erste Antwort zu geben, aber wenn Sie fragen, könnte ich abwarten, ob eine bessere Antwort kommt
Sanmai

Antworten:

1219
git pull -s recursive -X theirs <remoterepo or other repo>

Oder einfach für das Standard-Repository:

git pull -X theirs

Wenn Sie bereits in einem Konfliktzustand sind ...

git checkout --theirs path/to/file
Pascal Tarife
quelle
40
Beachten Sie, dass -s recursivehier redundant ist, da dies die Standard-Zusammenführungsstrategie ist. Sie könnten es also vereinfachen git pull -X theirs, was im Grunde gleichbedeutend ist mit git pull --strategy-option theirs.
5
Wenn ich das mache, lande ich wieder im MERGINGStaat. Ich kann es dann git merge --aborterneut versuchen, aber jedes Mal kommt es zu einer Zusammenführung. … Ich weiß, dass eine Rebase in meinen Upstream verschoben wurde. Vielleicht verursacht das das?
Benjohn
22
Sei vorsichtig mit git checkout --theirs path/to/file. Verwendet es während der Rebase und hat unerwartete Ergebnisse erhalten. Gefundene Erklärung in doc: Beachten Sie, dass während git rebase und git pull --rebase unsere und ihre möglicherweise getauscht erscheinen; --ours gibt die Version aus dem Zweig an, auf die die Änderungen neu basiert, während --theirs die Version aus dem Zweig angibt, in der sich Ihre Arbeit befindet, die neu basiert wird.
Vuk Djapic
10
Beachten Sie, dass die git checkout --theirs/--ours pathManpage angibt, dass sie für nicht zusammengeführte Pfade funktioniert . Wenn es also keinen Pfadkonflikt gab, der bereits zusammengeführt wurde, führt dieser Befehl nichts aus. Dies kann zu Problemen führen, wenn Sie beispielsweise die Version eines ganzen Unterordners "ihre" möchten. In einem solchen Fall wäre es also sicherer, git checkout MERGE_HEAD pathCommit-Hash auszuführen oder zu verwenden.
Fsw
4
git pull -X theirsErstellt ein Merge-Commit, wenn Konflikte vorliegen (z. B. wenn ein anderer Committer git push -fauf die Fernbedienung ausgeführt wurde). Wenn Sie keine Merge-Commits möchten, führen Sie stattdessen aus git fetch && git reset --hard origin/master.
Dan Dascalescu
985

Sie können die rekursive „ihre“ Strategie verwenden Option :

git merge --strategy-option theirs

Vom Mann :

ours
    This option forces conflicting hunks to be auto-resolved cleanly by 
    favoring our version. Changes from the other tree that do not 
    conflict with our side are reflected to the merge result.

    This should not be confused with the ours merge strategy, which does 
    not even look at what the other tree contains at all. It discards 
    everything the other tree did, declaring our history contains all that
    happened in it.

theirs
    This is opposite of ours.

Hinweis: als der Mann Seite sagt, das „unsere“ merge Strategie Option ist sehr verschieden von der „unserer“ merge Strategie .

Ikke
quelle
Hier ist eine detailliertere Erklärung: lostechies.com/joshuaflanagan/2010/01/29/…
mPrinC
227
Auch git checkout --theirsum eine einzelne widersprüchliche Datei zu
bearbeiten
48
Dies funktioniert nicht, wenn Sie sich bereits im Konfliktlösungsstatus befinden. In diesem Fall glaube ich , die beste Art und Weise zu lösen ist git checkout <ref to theirs> -- the/conflicted.file; und dann git addihre Änderungen.
ThorSummoner
54
@ThorSummoner In diesem Fall gibt es eine Git-Kasse - ihren Pfad / von / Datei. Auf diese Weise müssen Sie den richtigen Hash nicht manuell nachschlagen.
Ikke
8
@Ikke Das sollte im Grunde seine eigene Antwort sein (und die akzeptierte Antwort dazu), wenn du mich fragst.
ThorSummoner
473

Wenn Sie sich bereits in einem Konfliktzustand befinden und einfach alle akzeptieren möchten :

git checkout --theirs .
git add .

Wenn Sie das Gegenteil tun möchten:

git checkout --ours .
git add .

Das ist ziemlich drastisch, also stellen Sie sicher, dass Sie wirklich alles so auslöschen möchten, bevor Sie es tun.

viel zu lernen
quelle
47
Oder verwenden Sie nicht die .und geben Sie die Datei (en) anstelle des Punkts an, den Sie auschecken möchten. weniger "drastisch" und genau das, was Sie vermutlich tun möchten.
Manroe
10
Dies funktioniert nicht, wenn die Datei aus dem anderen Zweig entfernt wurde: '<Datei>' hat keine Version
Japster24
3
Würde mehr stimmen, wenn ich könnte, immer wieder auf diese Antwort zurückkommen.
Tarikki
6
Verwenden Sie git add -ustattdessen, um Dateien zu überspringen, die nicht der Versionskontrolle unterliegen.
Sudipta Basak
3
Hypothetischer Fall, drei Änderungen in einer Datei, eine widersprüchliche, zwei ohne Konflikt. Würde diese Lösung nicht widersprüchliche Änderungen anwenden und die widersprüchliche Änderung auf unsere auflösen? Oder würde es nur unsere Version brauchen, um nicht widersprüchliche Änderungen von ihren zu ignorieren?
Pedromarce
222

OK, stellen Sie sich das Szenario vor, in dem ich mich gerade befand:

Sie versuchen ein mergeoder vielleicht ein cherry-pick, und Sie werden mit gestoppt

$ git cherry-pick 1023e24
error: could not apply 1023e24... [Commit Message]
hint: after resolving the conflicts, mark the corrected paths
hint: with 'git add <paths>' or 'git rm <paths>'
hint: and commit the result with 'git commit'

Jetzt sehen Sie die in Konflikt stehende Datei und möchten Ihre Änderungen wirklich nicht behalten. In meinem obigen Fall war die Datei nur in einer neuen Zeile in Konflikt geraten, die meine IDE automatisch hinzugefügt hatte. Der einfachste Weg, um Ihre Änderungen rückgängig zu machen und zu akzeptieren, ist:

git checkout --theirs path/to/the/conflicted_file.php
git add path/to/the/conflicted_file.php

Das Gegenteil davon (um die eingehende Version mit Ihrer Version zu überschreiben) ist

git checkout --ours path/to/the/conflicted_file.php
git add path/to/the/conflicted_file.php

Überraschenderweise konnte ich diese Antwort im Internet nicht so einfach finden.

Theodore R. Smith
quelle
15
Beachten Sie, dass, wenn ein git statusZwischen- checkoutund ausgeführt wird add, die Datei weiterhin als "beide geändert" angezeigt wird.
Bischof
Wissen Sie, ob es eine Möglichkeit gibt, dies für alle Dateien zu tun, die sich in einem Konfliktzustand befinden? Wenn ja, wäre es eine schöne Erweiterung Ihrer Antwort.
Drew Noakes
2
Ich mache das: git reset --hard und dann git pull [remote server name] [branch name] -Xtheirs(macht die Zusammenführung rückgängig und zieht dann das neue Zeug über mein Zeug) - nicht sicher, ob dies das ist, was du willst.
Ssaltman
38

Die git pull -X theirsAntworten können zu einem hässlichen Zusammenführungs-Commit führen oder ein Commit ausgeben

Fehler: Ihre lokalen Änderungen an den folgenden Dateien werden durch Zusammenführen überschrieben:

Wenn Sie lokale Änderungen an Dateien aus dem Repo einfach ignorieren möchten, z. B. auf einem Client, der immer ein Spiegel eines Ursprungs sein sollte, führen Sie dies aus (ersetzen masterSie ihn durch den gewünschten Zweig):

git fetch && git reset --hard origin/master

Wie funktioniert es? git fetchtut git pullaber ohne zu verschmelzen . Dann git reset --hardstimmt Ihr Arbeitsbaum mit dem letzten Commit überein. Alle Ihre lokalen Änderungen an Dateien im Repo werden verworfen , aber neue lokale Dateien werden in Ruhe gelassen.

Dan Dascalescu
quelle
1
+1 - hat git fetch && git reset --hard {remote}/{branch}mein Problem gelöst. Ich musste meine eigenen Änderungen vollständig zugunsten des "ihren" Status eines Zweigs fallen lassen, aber das git pull -X theirserstickte an einigen verschobenen / umbenannten Dateien. Vielen Dank!
Ivaylo Slavov
23

Nach dem Zusammenführen von Git, wenn Sie Konflikte bekommen und entweder Ihre oder ihre wollen

git checkout --theirs .
git checkout --ours .
Mohit Kanojia
quelle
Wie würde ich das pro widersprüchlichem Block tun? Das Obige funktioniert auf Dateiebene und wirft alle nicht widersprüchlichen Blöcke aus, die eine in Konflikt stehende Datei möglicherweise hat.
Jani
21

So lösen Sie alle Konflikte mit der Version in einem bestimmten Zweig:

git diff --name-only --diff-filter=U | xargs git checkout ${branchName}

Wenn Sie sich also bereits im Zusammenführungsstatus befinden und die Master-Version der in Konflikt stehenden Dateien beibehalten möchten:

git diff --name-only --diff-filter=U | xargs git checkout master
Ariel Alvarez
quelle
Und wie wird dies für Benutzer von Fenstern ohne Zugriff auf Pipe-Xargs übersetzt?
Tsemer
Würde es Ihre Änderungen nicht komplett überspringen? Auch diejenigen, die sich nicht im Konfliktzustand befinden?
Valentin Heinitz
Das habe ich letztendlich getan. Leider ist später entweder ein git cherry-pick --continue oder ein git commit --allow-emptyBefehl erforderlich , um diese Änderungen zu übernehmen, und es scheint kein System zu geben, hinter dem ein Befehl erforderlich ist, was die Automatisierung zu einem Problem macht. Ich .git/COMMIT_EDITMSGlöse dies derzeit, indem ich prüfe, ob eine Datei vorhanden ist, aber das scheint hackig und spröde zu sein, und ich bin noch nicht davon überzeugt, dass es immer funktioniert.
Konrad Rudolph
Dies ist gut, dh wenn Sie einige manuell auflösen (und dies auch tun git add), können Sie den Rest über dieses Problem in großen Mengen auflösen. git checkout --oursIch git checkout --theirsbin auch nützlich.
Gruppe
18

Bitte nicht, dass dies manchmal nicht funktioniert :

git checkout - unser Pfad / zu / Datei

oder

Git Checkout - Ihr Pfad / zu / Datei

Ich habe dies stattdessen getan, vorausgesetzt, HEAD gehört uns und MERGE_HEAD gehört ihnen

git checkout HEAD -- path/to/file

oder:

git checkout MERGE_HEAD -- path/to/file

Nachdem wir das gemacht haben und wir sind gut:

git add .

Wenn Sie mehr verstehen möchten, lesen Sie den wunderbaren Beitrag von torek hier: git checkout --ours entfernt keine Dateien aus der Liste der nicht zusammengeführten Dateien

Nicolas D.
quelle
12

VS Code (integrierte Git) IDE Benutzer:

Wenn Sie alle eingehenden Änderungen in der Konfliktdatei akzeptieren möchten, führen Sie die folgenden Schritte aus.

1. Go to command palette - Ctrl + Shift + P
2. Select the option - Merge Conflict: Accept All Incoming

Ebenso können Sie für andere Optionen wie Alle beide akzeptieren, Alle aktuellen akzeptieren usw. tun.

SridharKritha
quelle
2
Das scheint nur für eine einzelne Datei zu funktionieren, nicht für alle Dateien mit Konflikten.
Yoryo
1

Ich hatte einen langjährigen next-versionZweig mit unzähligen Löschungen von Dateien, die geändert wurden develop, Dateien, die an verschiedenen Stellen in beiden Zweigen hinzugefügt wurden usw.

Ich wollte den gesamten Inhalt des next-versionZweigs in developeinem einzigen Merge-Commit zusammenfassen.

Die Kombination der oben genannten Befehle, die für mich funktioniert hat, war:

git merge -X theirs next-version
# lots of files left that were modified on develop but deleted on next-version
git checkout next-version .
# files removed, now add the deletions to the commit
git add .
# still have files that were added on develop; in my case they are all in web/
git rm -r web

Keine neue Antwort, sondern nur die Kombination von Bits aus vielen Antworten, teilweise um sicherzustellen, dass Sie möglicherweise alle diese Antworten benötigen .

Gordon
quelle
1

Wenn Sie sich bereits in einem Konfliktzustand befinden und den Pfad nicht einzeln auschecken möchten. Sie können es versuchen

git merge --abort
git pull -X theirs
Lee Chee Kiam
quelle
-1

von https://git-scm.com/book/en/v2/Git-Tools-Advanced-Merging

Dies führt im Grunde genommen zu einer gefälschten Zusammenführung. Es wird ein neues Zusammenführungs-Commit mit beiden Zweigen als übergeordnete Zweige aufgezeichnet, es wird jedoch nicht einmal der Zweig angezeigt, in dem Sie zusammenführen. Es wird einfach als Ergebnis der Zusammenführung den genauen Code in Ihrem aktuellen Zweig aufgezeichnet.

$ git merge -s ours mundo

Zusammenführung durch die Strategie "Unsere".

$ git diff HEAD HEAD~

Sie können sehen, dass es keinen Unterschied zwischen dem Zweig, in dem wir uns befanden, und dem Ergebnis der Zusammenführung gibt.

Dies kann oft nützlich sein, um Git zu der Annahme zu verleiten, dass ein Zweig bereits zusammengeführt wird, wenn später eine Zusammenführung durchgeführt wird. Angenommen, Sie haben einen Release-Zweig abgezweigt und einige Arbeiten daran durchgeführt, die Sie irgendwann wieder in Ihren Master-Zweig einbinden möchten. In der Zwischenzeit muss ein Bugfix auf dem Master in Ihren Release-Zweig zurückportiert werden. Sie können den Bugfix-Zweig mit dem Release-Zweig zusammenführen und unseren Zweig auch mit Ihrem Hauptzweig zusammenführen (obwohl der Fix bereits vorhanden ist). Wenn Sie den Release-Zweig später erneut zusammenführen, treten keine Konflikte mit dem Bugfix auf.

Eine Situation, die ich als nützlich empfunden habe, wenn der Master die Änderungen eines neuen Themenzweigs widerspiegeln soll. Mir ist aufgefallen, dass -Xtheirs unter bestimmten Umständen nicht ohne Konflikte verschmelzen ... z

$ git merge -Xtheirs topicFoo 

CONFLICT (modify/delete): js/search.js deleted in HEAD and modified in topicFoo. Version topicFoo of js/search.js left in tree.

In diesem Fall war die Lösung, die ich gefunden habe

$ git checkout topicFoo

Wenn Sie in topicFoo zuerst den Master mit der Strategie -s our zusammenführen, wird das falsche Commit erstellt, das nur den Status von topicFoo darstellt. $ git verschmilzt mit unserem Meister

Überprüfen Sie das erstellte Zusammenführungs-Commit

$ git log

Kasse jetzt den Hauptzweig aus

$ git checkout master

Führen Sie den Themenzweig wieder zusammen, aber verwenden Sie diesmal die rekursive Strategie -Xtheirs. Dadurch wird Ihnen jetzt ein Hauptzweig mit dem Status von topicFoo angezeigt.

$ git merge -X theirs topicFoo
Amos Folarin
quelle