Wie kann ich Remote-Änderungen verwerfen und eine Datei als "gelöst" markieren?

197

Ich habe einige lokale Dateien, ich ziehe aus dem Remote-Zweig und es gibt Konflikte. Ich weiß, dass ich meine lokalen Änderungen beibehalten und die Remote-Änderungen, die Konflikte verursachen, ignorieren möchte. Gibt es einen Befehl, mit dem ich tatsächlich sagen kann: "Alle Konflikte als gelöst markieren, lokal verwenden"?

Tom DeMille
quelle
1
Die Antwort unten war für mich sehr aufschlussreich. Es gibt ein paar subtile Punkte, die die Dinge für mich wirklich klar machen. Ich empfehle jedem nicht erfahrenen GIT-Benutzer, alle Kommentare unter dem Beitrag unten zu lesen, und danke Brian!
Tom DeMille

Antworten:

332

git checkouthat die --oursOption, die Version der Datei auszuchecken, die Sie lokal hatten (im Gegensatz zu --theirsder Version, die Sie eingezogen haben). Sie können .an übergeben git checkout, um es anzuweisen, alles im Baum zu überprüfen. Dann müssen Sie die Konflikte als gelöst markieren, mit denen Sie git addfertig werden können , und Ihre Arbeit nach Abschluss erledigen:

git checkout --ours .  # checkout our local version of all files
git add -u             # mark all conflicted files as merged
git commit             # commit the merge

Beachten Sie die .im git checkoutBefehl. Das ist sehr wichtig und leicht zu übersehen. git checkouthat zwei Modi; eine, in der Zweige gewechselt werden, und eine, in der Dateien aus dem Index in die Arbeitskopie eingecheckt werden (manchmal werden sie zuerst aus einer anderen Revision in den Index gezogen). Es unterscheidet sich dadurch, ob Sie einen Dateinamen übergeben haben. Wenn Sie keinen Dateinamen übergeben haben, wird versucht, die Zweige zu wechseln (wenn Sie jedoch auch keinen Zweig übergeben, wird nur versucht, den aktuellen Zweig erneut auszuchecken), dies wird jedoch abgelehnt, wenn geänderte Dateien vorhanden sind dass das bewirken würde. Wenn Sie also ein Verhalten wünschen, das vorhandene Dateien überschreibt, müssen Sie .einen Dateinamen übergeben, um das zweite Verhalten zu erhalten git checkout.

Es ist auch eine gute Angewohnheit, bei der Übergabe eines Dateinamens diesen auszugleichen --, z git checkout --ours -- <filename>. Wenn Sie dies nicht tun und der Dateiname zufällig mit dem Namen eines Zweigs oder Tags übereinstimmt, wird Git denken, dass Sie diese Revision auschecken möchten, anstatt diesen Dateinamen auszuchecken, und daher die erste Form des checkoutBefehls verwenden .

Ich werde etwas näher darauf eingehen, wie Konflikte und Zusammenführungen in Git funktionieren. Wenn Sie den Code einer anderen Person zusammenführen (was auch während eines Pulls geschieht; ein Pull ist im Wesentlichen ein Abruf, gefolgt von einem Zusammenführen), gibt es nur wenige mögliche Situationen.

Das einfachste ist, dass Sie sich in derselben Revision befinden. In diesem Fall sind Sie "bereits auf dem neuesten Stand" und es passiert nichts.

Eine andere Möglichkeit besteht darin, dass ihre Revision einfach ein Nachkomme von Ihnen ist. In diesem Fall haben Sie standardmäßig eine "Schnellvorlauf-Zusammenführung", bei der Ihre HEADVersion nur auf ihre Festschreibung aktualisiert wird, ohne dass eine Zusammenführung stattfindet (dies kann deaktiviert werden, wenn Sie dies tun) möchte wirklich eine Zusammenführung aufzeichnen, mit --no-ff).

Dann kommen Sie in die Situationen, in denen Sie tatsächlich zwei Revisionen zusammenführen müssen. In diesem Fall gibt es zwei mögliche Ergebnisse. Eine ist, dass die Zusammenführung sauber erfolgt; Alle Änderungen befinden sich in verschiedenen Dateien oder in denselben Dateien, sind jedoch so weit voneinander entfernt, dass beide Änderungssätze problemlos angewendet werden können. Wenn eine saubere Zusammenführung stattfindet, wird diese automatisch festgeschrieben. Sie können dies jedoch deaktivieren, --no-commitwenn Sie sie zuvor bearbeiten müssen (wenn Sie beispielsweise die Funktion fooin umbenennen barund jemand anderes neuen Code hinzufügt, der aufruft foo, wird sie sauber zusammengeführt Wenn Sie jedoch einen fehlerhaften Baum erstellen, sollten Sie diesen im Rahmen des Zusammenführungs-Commits bereinigen, um zu vermeiden, dass defekte Commits ausgeführt werden.

Die letzte Möglichkeit ist, dass es eine echte Verschmelzung gibt und es Konflikte gibt. In diesem Fall wird tun Git so viel von der Zusammenführung , wie sie können, und produzieren Dateien mit Konfliktmarken ( <<<<<<<, =======, und >>>>>>>) in Ihrer Arbeitskopie. Im Index (auch als "Staging-Bereich" bezeichnet; der Ort, an dem Dateien gespeichert werden, git addbevor sie festgeschrieben werden) befinden sich 3 Versionen jeder Datei mit Konflikten. Es gibt die Originalversion der Datei vom Vorfahren der beiden Zweige, die Sie zusammenführen, die Version von HEAD(Ihre Seite der Zusammenführung) und die Version vom Remote-Zweig.

Um den Konflikt zu lösen, können Sie entweder die Datei in Ihrer Arbeitskopie bearbeiten, die Konfliktmarkierungen entfernen und den Code so korrigieren, dass er funktioniert. Oder können Sie die Version von einem oder den anderen Seiten der Zusammenführung überprüfen, mit git checkout --oursoder git checkout --theirs. Sobald Sie die Datei in den gewünschten Zustand versetzt haben, geben Sie an, dass Sie mit dem Zusammenführen der Datei fertig sind und sie zum Festschreiben bereit ist. git addAnschließend können Sie die Zusammenführung mit festschreiben git commit.

Brian Campbell
quelle
7
Sie sollten wahrscheinlich beachten, dass git add --allalle Dateien zum Repository hinzugefügt werden, sodass möglicherweise mehr Dateien als beabsichtigt hinzugefügt werden, es sei denn, Ihre .gitignoreMuster befinden sich in einem perfekten Zustand. git add -uist wahrscheinlich besser für diese Situation geeignet. Es ist weniger wahrscheinlich, dass Sie Änderungen an nachverfolgten Dateien vornehmen, die Sie beim Auflösen einer Zusammenführung nicht hinzufügen möchten.
CB Bailey
Ups, tut mir Leid. Das ist es was ich meinte. Korrigierte es jetzt.
Brian Campbell
1
Vielen Dank für Ihre ausführliche Antwort. Ich habe tatsächlich git checkout --ours ausprobiert und eine Fehlermeldung erhalten (an die ich mich jetzt nicht erinnere). Die fraglichen Dateien sind DLLs (wir haben einige, die wir verstecken, meistens Referenzen von Drittanbietern) und ich wollte nur sagen: "OK, meine Kopie ist die, die ich möchte, aber der Fehler war so etwas wie" Beim Zusammenführen kann nicht ausgecheckt werden ". ..... Ich werde diesen Artikel als Referenz behalten und wenn es das nächste Mal passiert, versuchen Sie es erneut und prüfen Sie, ob es funktioniert oder ob ich diese Nachricht posten kann.
Tom DeMille
Aber Ihre Erklärung klärt mich sehr über den Prozess auf, nochmals vielen Dank ... Folgefrage: Gibt es eine Möglichkeit, git dazu zu bringen, die .orig-Dateien zu löschen, sobald die Zusammenführung abgeschlossen ist?
Tom DeMille
2
Du musst tun git checkout --ours .. Das .ist wichtig; Durch die Übergabe eines Dateinamens (in diesem Fall des gesamten Verzeichnisses) wird zwischen zwei verschiedenen Betriebsmodi von ausgewählt checkout, von denen einer die Zweige wechselt und einer die Dateien vom Index in die Arbeitskopie verschiebt. Ich stimme zu, es ist sehr verwirrend. Sie können auch git checkout --ours -- <filename>eine einzelne Datei gleichzeitig auschecken.
Brian Campbell
23

Stellen Sie sicher, dass der Konflikt entstanden ist: Wenn er das Ergebnis von a ist git merge, lesen Sie die Antwort von Brian Campbell .

Wenn dies jedoch das Ergebnis von a ist git rebase, müssten Sie Folgendes tun , um entfernte Änderungen zu verwerfen und lokale Änderungen zu verwenden:

git checkout --theirs -- .

Siehe " Warum ist die Bedeutung von" ours"und" theirs"umgekehrt" ", um zu sehen, wie oursund theirswährend einer Rebase ausgetauscht werden (da der Upstream- Zweig ausgecheckt ist).

VonC
quelle