Antworten:
Weil es keinen Sinn macht (andere Befehle bieten diese Funktionalität bereits an) und es das Risiko verringert, versehentlich das Falsche zu tun.
Ein "Hard Reset" für einen Pfad wird gerade durchgeführt git checkout HEAD -- <path>
(Auschecken der vorhandenen Version der Datei).
Ein Soft-Reset für einen Pfad macht keinen Sinn.
Ein gemischter Reset für einen Pfad ist das, was git reset -- <path>
bewirkt.
git checkout -- <path>
führt keinen Hard-Reset durch; Es ersetzt den Arbeitsbauminhalt durch den bereitgestellten Inhalt. git checkout HEAD -- <path>
führt einen Hard-Reset für einen Pfad durch und ersetzt sowohl den Index als auch den Arbeitsbaum durch die Version aus dem HEAD-Commit.
reset --hard
mit einem Pfad würde dieses fehlende Stück liefern. Git ist bereits so mächtig, dass die Ausrede "Wir lassen Sie das nicht zu Ihrem eigenen Schutz tun" kein Wasser enthält: Es gibt viele Möglichkeiten, "aus Versehen" das Falsche zu tun. Nichts davon ist sowieso wichtig, wenn Sie haben git reflog
.
git reset --hard -- <path>
. Es gibt legitime Anwendungsfälle dafür.
Sie können das erreichen, was Sie damit versuchen git checkout HEAD <path>
.
Die bereitgestellte Fehlermeldung macht für mich jedoch keinen Sinn (da sie git reset
in Unterverzeichnissen einwandfrei funktioniert), und ich sehe keinen Grund, warum Sie git reset --hard
nicht genau das tun sollten, was Sie von ihr verlangen.
Die Frage wie wird schon beantwortet , ich erkläre den Warum- Teil.
Also, was macht Git Reset ? Abhängig von den angegebenen Parametern kann es zwei verschiedene Dinge tun:
Wenn Sie einen Pfad angeben, werden die übereinstimmenden Dateien im Index durch die Dateien aus einem Commit ersetzt (standardmäßig HEAD). Diese Aktion wirkt sich überhaupt nicht auf den Arbeitsbaum aus und wird normalerweise als Gegenteil von git add verwendet.
Wenn Sie keinen Pfad angeben, wird der aktuelle Verzweigungskopf in ein bestimmtes Commit verschoben und zusammen mit diesem optional der Index und der Arbeitsbaum auf den Status dieses Commits zurückgesetzt. Dieses zusätzliche Verhalten wird durch den Parameter mode gesteuert:
--soft : Berühren Sie nicht den Index und den Arbeitsbaum.
--mixed (Standard): Setzt den Index zurück, aber nicht den Arbeitsbaum.
--hard : Index und Arbeitsbaum zurücksetzen.
Es gibt auch andere Optionen. Die vollständige Liste und einige Anwendungsfälle finden Sie in der Dokumentation.
Wenn Sie kein Commit angeben, wird standardmäßig HEAD verwendet, sodass git reset --soft
nichts unternommen wird, da es sich um einen Befehl handelt, den Kopf in HEAD (in den aktuellen Status) zu verschieben. git reset --hard
Auf der anderen Seite ist es aufgrund seiner Nebenwirkungen sinnvoll , den Kopf auf HEAD zu bewegen und den Index und den Arbeitsbaum auf HEAD zurückzusetzen.
Ich denke, es sollte jetzt klar sein, warum dieser Vorgang von Natur aus nicht für bestimmte Dateien gilt - er soll in erster Linie einen Verzweigungskopf verschieben, den Arbeitsbaum zurücksetzen und der Index ist eine sekundäre Funktionalität.
git checkout
Befehl verfügbar ist ? Ein Zurücksetzen, um dasselbe zu tun, würde die Benutzer weiter verwirren. Meine Antwort war, dass diese --hard
Option nicht auf bestimmte Dateien anwendbar ist, da es sich um einen Modus zum Zurücksetzen von Zweigen und nicht zum Zurücksetzen von Indizes handelt. Das Zurücksetzen des Arbeitsbaums wird als Kasse bezeichnet, wie Sie in anderen Antworten lesen können. All das ist nur ein schlechtes Design der Benutzeroberfläche von Git, IMHO.
git checkout
: git reset --
Setzt nur den Index, während git checkout --
nur der Arbeitsbaum festgelegt wird?
Stellen Sie sicher, dass Sie einen Schrägstrich zwischen Ursprung oder Upstream (Quelle) und dem tatsächlichen Zweig setzen:
git reset --hard origin/branch
oder
git reset --hard upstream/branch`
Dahinter steckt ein sehr wichtiger Grund: die Prinzipien von checkout
undreset
.
In Git-Begriffen bedeutet Auschecken "In den aktuellen Arbeitsbaum bringen". Und mit können git checkout
wir den Arbeitsbaum mit Daten aus jedem Bereich füllen , sei es aus einem Commit im Repository oder aus einzelnen Dateien aus einem Commit oder dem Staging-Bereich (dies ist sogar die Standardeinstellung).
Git Reset hat diese Rolle wiederum nicht. Wie der Name schon sagt, wird die aktuelle Referenz zurückgesetzt, wobei jedoch immer das Repository als Quelle verwendet wird, unabhängig von der "Reichweite" (--soft, --mixed oder --hard).
Rekapitulieren:
Was daher etwas verwirrend sein kann, ist die Existenz von git reset COMMIT -- files
"Überschreiben von HEAD" mit nur einigen Dateien macht keinen Sinn!
In Ermangelung einer offiziellen Erklärung kann ich nur spekulieren, dass die Git-Entwickler festgestellt haben, dass dies reset
immer noch der beste Name für einen Befehl zum Verwerfen von Änderungen ist, die am Staging-Bereich vorgenommen wurden, und angesichts der einzigen Datenquelle, die das Repository war, "erweitern wir das Funktionalität "anstatt einen neuen Befehl zu erstellen.
Irgendwie git reset -- <files>
ist das schon ein bisschen außergewöhnlich: Es wird den KOPF nicht überschreiben. IMHO wären alle diese Variationen Ausnahmen. Selbst wenn wir uns eine --hard
Version vorstellen können , --soft
wären andere (zum Beispiel ) nicht sinnvoll.
git reset -- <files>
fiel wie es hinzugefügt wurde, weil dies eine nützliche Funktion ist, aber niemand war sicher, in welchen Befehl es gesetzt werden sollte. Zum Glück haben wir jetzt viel vernünftigere git restore
Funktionen mit git checkout -- <path>
git checkout <commit> -- <path>
und git reset [<commit>] -- <path>
mit viel vernünftigeren Standardeinstellungen und noch mehr Funktionen, die Sie vorher nicht ausführen konnten (Entgegen der akzeptierten Antwort. Jetzt können Sie endlich einfach nur einen funktionierenden Baum wiederherstellen, ohne den Index zu berühren).
Das git reset
Handbuch listet drei Arten des Aufrufs auf:
2 sind dateiweise: Diese wirken sich nicht auf den Arbeitsbaum aus , sondern wirken sich nur auf die Dateien in dem Index aus, der durch Folgendes angegeben ist <paths>
:
git reset [-q] [<tree-ish>] [--] <paths>..
git reset (--patch | -p) [<tree-ish>] [--] [<paths>...]
1 ist Commit-weise: Funktioniert mit allen Dateien in der referenzierten Datei<commit>
und kann sich auf den Arbeitsbaum auswirken:
git reset [<mode>] [<commit>]
Es gibt keinen Aufrufmodus, der nur für bestimmte Dateien gilt und sich auf den Arbeitsbaum auswirkt.
Wenn Sie beides wollen:
Sie können diesen Alias in Ihrer Git-Konfigurationsdatei verwenden:
[alias]
reco = !"cd \"${GIT_PREFIX:-.}\" && git reset \"$@\" && git checkout \"$@\" && git status --short #" # Avoid: "fatal: Cannot do hard reset with paths."
Sie können dann einen der folgenden Schritte ausführen:
$ git reco <paths>
$ git reco <branch/commit> <paths>
$ git reco -- <paths>
(Mnenonic für reco
: re
set && c
heck o
ut)
git checkout -- <path>
sollte durch ersetzt werdengit reset --hard <path>
. Es macht so viel mehr Sinn ...