it-swarm.com.de

Warum kann git keine harten/weichen Reset-Vorgänge durchführen?

$ git reset -- <file_path> kann nach Pfad zurückgesetzt werden.

$ git reset (--hard|--soft) <file_path> meldet jedoch einen Fehler wie folgt:

Cannot do hard|soft reset with paths.
105
yao

Weil es keinen Sinn macht (andere Befehle bieten diese Funktionalität bereits an) und verringert das Risiko, dass Sie aus Versehen etwas Falsches tun.

Ein "Hard Reset" für einen Pfad erfolgt einfach mit git checkout HEAD -- <path> (Auschecken der vorhandenen Version der Datei).

Ein Soft Reset für einen Pfad ist nicht sinnvoll.

Ein gemischter Reset für einen Pfad ist das, was git reset -- <path> tut.

114
Amber

Sie können erreichen, was Sie mit git checkout HEAD <path> versuchen.

Die angegebene Fehlermeldung macht für mich jedoch keinen Sinn (da git reset gut für Unterverzeichnisse funktioniert), und ich sehe keinen Grund, warum git reset --hard nicht genau das tun soll, was Sie davon verlangen. 

17
Aaron Kent

Die Frage wie ist bereits beantwortet , ich erkläre den warum-Teil.

Also, was macht git reset ? Abhängig von den angegebenen Parametern können zwei verschiedene Aufgaben ausgeführt werden:

  • Wenn Sie einen Pfad angeben, werden die übereinstimmenden Dateien im Index durch die Dateien eines Commits (standardmäßig HEAD) ersetzt. Diese Aktion hat keinerlei Auswirkungen auf den Arbeitsbaum und wird normalerweise als Gegenteil von git add verwendet.

  • Wenn Sie keinen Pfad angeben, verschiebt er den aktuellen Zweigkopf zu einem angegebenen Commit und setzt zusammen mit diesem optional den Index und die Arbeitsstruktur auf den Status dieses Commits zurück. Dieses zusätzliche-Verhalten wird durch den Modusparameter gesteuert:
    --soft: Berühren Sie nicht den Index und den Arbeitsbaum.
    --mixed (Standardeinstellung): setzt den Index zurück, nicht jedoch den Arbeitsbaum.
    --hard: setzt den Index und den Arbeitsbaum zurück.
    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. git reset --soft unternimmt nichts, da es ein Befehl ist, den Kopf auf HEAD (in den aktuellen Status) zu verschieben. git reset --hard hingegen ist aufgrund seiner Nebenwirkungen sinnvoll, heißt es, bewegen Sie den Kopf auf HEAD und und setzen Sie den Index und den Arbeitsbaum auf HEAD zurück.

    Ich denke, es sollte inzwischen klar sein, warum diese Operation naturgemäß nicht für bestimmte Dateien bestimmt ist. Sie soll einen Zweigkopf überhaupt verschieben, den Arbeitsbaum zurücksetzen und den Index als sekundäre Funktionalität verwenden.

7
user

Stellen Sie sicher, dass Sie einen Schrägstrich zwischen Origin oder Upstream (Quelle) und dem tatsächlichen Zweig einfügen:

git reset --hard Origin/branch

oder

git reset --hard upstream/branch`
2
Pascal Nitcheu

Erläuterung

Das git reset - Handbuch listet 3 Aufrufmöglichkeiten auf:

  • 2 sind dateibezogen: Diese wirken sich nicht auf den Arbeitsbaum aus , sondern wirken sich nur auf die Dateien in dem durch <paths> Angegebenen Index aus:

    • git reset [-q] [<tree-ish>] [--] <paths>..
    • git reset (--patch | -p) [<tree-ish>] [--] [<paths>...]
  • 1 ist festschreibungsmäßig: Wirkt auf alle Dateien , auf die sich <commit> Und may beziehen der arbeitende Baum:

    • git reset [<mode>] [<commit>]

Es gibt keinen Aufrufmodus, der nur für bestimmte Dateien ausgeführt wird. und wirkt sich auf den Arbeitsbaum aus.

Workaround

Wenn Sie beides wollen:

  • Zurücksetzen der Index-/Cache-Version einer Datei (en)
  • Checken Sie die Datei (en) aus (dh stellen Sie sicher, dass der Arbeitsbaum mit dem Index und der Commit-Version übereinstimmt).

Sie können diesen Alias ​​in Ihrer Git-Konfigurationsdatei verwenden:

[alias]
  reco   = !"cd \"${GIT_PREFIX:-.}\" && git reset \"[email protected]\" && git checkout \"[email protected]\" && git status --short #"  # Avoid: "fatal: Cannot do hard reset with paths."

Sie können dann eine der folgenden Aktionen ausführen:

$ git reco <paths>

$ git reco <branch/commit> <paths>

$ git reco -- <paths>

(Mnenonic für reco: reset && check out)

0
Tom Hale

Dafür gibt es einen sehr wichtigen Grund: die Prinzipien von checkout und reset.

In Git-Begriffen bedeutet checkout "in den aktuellen Arbeitsbaum bringen". Und mit git checkout Können wir den Arbeitsbaum mit Daten aus jedem Bereich füllen, sei es aus einem Commit im Repository oder einzelne Dateien aus einem Commit oder dem Staging-Bereich (das ist sogar die Standardeinstellung).

Git reset hat diese Rolle wiederum nicht. Wie der Name schon sagt, wird der aktuelle Verweis zurückgesetzt, aber hat immer das Repository als Quelle, unabhängig von der "Reichweite" (- weich, gemischt oder hart).

Rekapitulieren:

  • checkout : Von überall (Index/Repo Commit) -> Arbeitsbaum
  • reset : Repo commit -> Overwrite HEAD (und optional index und working tree)

Daher kann die Existenz von git reset COMMIT -- files Etwas verwirrend sein, da das "Überschreiben von HEAD" mit nur einigen Dateien keinen Sinn ergibt!

In Ermangelung einer offiziellen Erklärung kann ich nur spekulieren, dass die Git-Entwickler festgestellt haben, dass reset immer noch der beste Name für einen Befehl zum Verwerfen von Änderungen im Staging-Bereich ist und dass die einzige Datenquelle das Repository ist , dann " lassen Sie uns die Funktionalität erweitern ", anstatt einen neuen Befehl zu erstellen.

Irgendwie ist git reset -- <files> Schon ein bisschen außergewöhnlich: Es wird den HEAD nicht überschreiben. IMHO alle solche Variationen wären Ausnahmen. Selbst wenn wir uns eine --hard - Version vorstellen könnten, würden andere (zum Beispiel --soft) Keinen Sinn ergeben.

0
F Pereira