714 Stimmen

Wie löst man einen Git Stash-Konflikt ohne Commit?

Als in dieser Frage gefragt Ich möchte auch wissen, wie man einen Konflikt auflöst git stash pop ohne alle Änderungen zu einem Commit hinzuzufügen (so wie es "git stash pop" ohne Konflikt tut).

Mein derzeitiger Ansatz ist sehr uncool, weil ich es auf diese Weise mache:

git stash pop  # -> CONFLICT
git stash drop
# [resolve conflict]
# [add conflict files]
git reset HEAD # <all files that are in commit-mode>

Wie man sich fortpflanzt:

mkdir foo; cd foo; git init
echo "1" > one
echo "2" > two
git add -A; git commit -m "first"
echo "1.1" > one
echo "2.1" > two
git stash
echo "2.2" > two
git commit -a -m "second"
echo "Only this file would stay in HEAD without the conflict" > third
git add third
git stash pop
git status

2016-06-27: Dem Beispiel wurde eine neue Datei namens 'third' hinzugefügt, um zu zeigen, dass Workarounds wie die Lösung von scy nur für leere HEADs funktionieren, aber nicht das ursprüngliche Problem beheben, dass der HEAD nicht denselben Inhalt hat wie bei einem git stash pop ohne einen Konflikt.

866voto

Folgen Sie nicht den anderen Antworten...

Nun, man kann ihnen natürlich folgen. Aber ich glaube nicht, dass ein Commit und das anschließende Zurücksetzen der Verzweigung, um den Commit zu entfernen, den Sie gerade erstellt haben, und ähnliche in anderen Antworten vorgeschlagene Workarounds der saubere Weg sind, dieses Problem zu lösen.

Saubere Lösung

Die folgende Lösung scheint mir viel sauberer zu sein, und sie ist auch von der Git selbst vorgeschlagen - versuchen, auszuführen git status im Repository mit einem Konflikt:

Unmerged paths:
  (use "git restore --staged <file>..." to unstage)
  (use "git add <file>..." to mark resolution)

Anmerkung: Die restore Befehl ist in Git eingeführt worden Version 2.23.0 . Ältere Versionen von Git schlugen vor, den Befehl git reset HEAD <file>... anstelle von git restore --staged <file>... . Sie können auch Folgendes verwenden git reset um alle Dateien im Staging-Bereich zu entsperren (genannt die Index ). Das Äquivalent des Befehls Restore ist git restore --staged . (der Punkt ist notwendig und gibt eine beliebige Datei an). Derzeit, jeder dieser Befehle kann verwendet werden und das Ergebnis ist das gleiche . Wenn Sie mehr über die Unterschiede zwischen diesen Befehlen erfahren möchten, lesen Sie die Dokumentation .

Tun wir also, was Git vorschlägt ( ohne sinnlose Übertragungen vorzunehmen und rückgängig zu machen ):

  1. Manuell (oder idealerweise mit Hilfe einer Merge-Tool (siehe unten) den Konflikt/die Konflikte lösen.)
  2. 使用方法 git restore --staged . Konflikt(e) als gelöst und ungelöst markieren alle Dateien im Staging-Bereich. Wenn Sie nur bestimmte Dateien aus dem Staging-Bereich entfernen möchten, verwenden Sie den Befehl git restore --staged <file> stattdessen. Sie müssen nicht ausführen git add vor.
  3. Schließlich entfernen Sie das Versteck mit git stash drop weil Git dies bei Konflikten nicht automatisch tut.

Übersetzt in die Befehlszeilenbefehle:

$ git stash pop

# ...resolve conflict(s)

$ git restore --staged .

$ git stash drop

Erläuterung des Standardverhaltens

Es gibt zwei Möglichkeiten, Konflikte als gelöst zu markieren: git add y git restore --staged <file>... . Während git restore --staged <file>... markiert die Konflikte als gelöst und entfernt die Dateien aus dem Index, git add markiert die Konflikte ebenfalls als gelöst, behält aber die Dateien im Index.

Das Hinzufügen von Dateien zum Index, nachdem ein Konflikt behoben wurde, ist beabsichtigt. Auf diese Weise können Sie zwischen den Änderungen aus dem vorherigen Versteck und den Änderungen, die Sie nach der Konfliktlösung vorgenommen haben, unterscheiden. Wenn Ihnen das nicht gefällt, können Sie jederzeit git restore --staged . um alles aus dem Index zu entfernen.

Tools zum Zusammenführen

Ich empfehle dringend die Verwendung einer der 3-Wege-Zusammenführungswerkzeuge zur Lösung von Konflikten, z.B. KDiff3 , Melden usw., anstatt dies manuell zu tun. In der Regel löst es alle oder die meisten Konflikte automatisch selbst. Es ist riesig Zeitersparnis!

308voto

scy Punkte 6784

Nehmen wir an, Sie haben ein Szenario, in dem Sie Ihre Änderungen zwischenspeichern, um sie von origin zu ziehen. Möglicherweise, weil Ihre lokalen Änderungen nur debug: true in einer Einstellungsdatei. Jetzt ziehen Sie und jemand hat dort eine neue Einstellung eingeführt, wodurch ein Konflikt entsteht.

git status sagt:

# On branch master
# Unmerged paths:
#   (use "git reset HEAD <file>..." to unstage)
#   (use "git add/rm <file>..." as appropriate to mark resolution)
#
#   both modified:      src/js/globals.tpl.js
no changes added to commit (use "git add" and/or "git commit -a")

Okay. Ich entschied mich für den Vorschlag von Git: Ich löste den Konflikt und verpflichtete mich:

vim src/js/globals.tpl.js
# type type type …
git commit -a -m WIP   # (short for "work in progress")

Jetzt ist meine Arbeitskopie in dem Zustand, den ich haben möchte, aber ich habe eine Übergabe erstellt, die ich nicht haben möchte. Wie werde ich diesen Commit wieder los, ohne meine Arbeitskopie zu verändern? Moment, dafür gibt es einen bekannten Befehl!

git reset HEAD^

Meine Arbeitskopie wurde nicht verändert, aber die WIP-Übertragung ist verschwunden. Das ist genau das, was ich wollte! (Beachten Sie, dass ich nicht mit --soft hier, denn wenn sich in Ihrem Stash automatisch zusammengefasste Dateien befinden, werden sie automatisch ausgelagert, was dazu führt, dass diese Dateien nach der Auslagerung erneut ausgelagert werden. reset .)

Aber es gibt noch eine Sache, die übrig ist: Die Manpage für git stash pop erinnert uns daran, dass "Das Anwenden des Status kann bei Konflikten fehlschlagen; in diesem Fall wird er nicht aus der Stash-Liste entfernt. Sie müssen die Konflikte von Hand auflösen und die git stash drop manuell nach." Und genau das tun wir jetzt:

git stash drop

Und fertig.

94voto

ComputerDruid Punkte 15357

Anstatt die Änderungen hinzuzufügen, die Sie zur Lösung des Konflikts vornehmen, können Sie git reset HEAD file um den Konflikt zu lösen, ohne Ihre Änderungen bereitzustellen.

Möglicherweise müssen Sie diesen Befehl jedoch zweimal ausführen. Einmal, um den Konflikt als gelöst zu markieren, und einmal, um die Änderungen, die von der Konfliktlösungsroutine ausgelöst wurden, wieder rückgängig zu machen.

Es ist möglich, dass es einen Rücksetzmodus gibt, der beides gleichzeitig tut, obwohl es derzeit keinen gibt.

48voto

stevenspiel Punkte 5309
git checkout stash -- .

hat für mich funktioniert.

Hinweis : Dies kann gefährlich sein, da es nicht versucht, die Änderungen aus dem Versteck in die Arbeitskopie zu übernehmen, aber überschreibt es stattdessen mit den versteckten Dateien. So können Sie Ihre nicht übertragenen Änderungen verlieren.

38voto

Aaron Goldman Punkte 739
git add .
git reset

git add . stellt ALLE Dateien ein und teilt Git mit, dass Sie den Konflikt behoben haben

git reset hebt ALLE bereitgestellten Dateien auf, ohne eine Übergabe 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