Hard Reset einer einzelnen Datei

1006

Ich habe derzeit drei geänderte Dateien in meinem Arbeitsverzeichnis. Ich möchte jedoch, dass einer von ihnen auf den HEAD-Status zurückgesetzt wird.

In SVN würde ich verwenden svn revert <filename>(gefolgt von, svn update <filename>falls erforderlich), aber in Git sollte ich verwenden git reset --hard. Dieser Befehl kann jedoch nicht für eine einzelne Datei ausgeführt werden.

Gibt es in Git eine Möglichkeit, die Änderungen an einer einzelnen Datei zu verwerfen und mit einer neuen HEAD-Kopie zu überschreiben?

Emiliano
quelle
3
git checkoutUnten ist die Antwort. In git ist "Zurücksetzen" etwas, was Sie einem Commit antun. "Zurücksetzen" spielt die Umkehrung eines historischen Commits in Ihrem Arbeitsverzeichnis ab, sodass Sie ein neues Commit erstellen können, das das zurückgesetzte Commit "rückgängig macht". Ich finde, dies ist ein häufiger Punkt der Verwirrung für Leute, die von SVN zu Git kommen.
Dan Ray
Wenn Sie interessiert sind , warum Sie nicht mit Pfaden Hard Reset durchführen können, beachten Sie auch meine Antwort gibt .
Benutzer
Diese Frage setzt voraus, dass man weiß, was ein Hard Reset ist.

Antworten:

1810

Sie können den folgenden Befehl verwenden:

git checkout HEAD -- my-file.txt

... wodurch sowohl die Arbeitskopie my-file.txtals auch ihr Status im Index mit der von HEAD aktualisiert werden .

--bedeutet im Grunde: Behandle jedes Argument nach diesem Punkt als Dateinamen . Weitere Details in dieser Antwort . Vielen Dank an VonC für diesen Hinweis.

Mark Longair
quelle
58
Vollständigere Antwort. +1;) Für das '-' siehe auch stackoverflow.com/questions/6561142/… (und allgemeiner stackoverflow.com/questions/1192180/… )
VonC
8
Vergessen Sie auch nicht, dass Sie auf ein vorheriges Commit verweisen können HEAD~1, um das vorletzte Commit anzugeben.
Ryanmt
14
Sie können weglassen , HEADwenn Sie an der Spitze der aktuellen Niederlassung stehen - siehe norbauer.com/rails-consulting/notes/…
cxw
4
Gibt es eine Einsicht, warum der resetBefehl (wie es heißt) "kein Hard-Reset mit Pfaden durchführen kann" und warum der checkoutBefehl dann nicht (kann nicht?) Zum Hard-Reset des gesamten Satzes verwendet wird? (Ich meine, warum es so entworfen wurde.)
Gr.
1
@cxw Leider ist das nicht ganz richtig. Aus der Manpage von git checkout: "Überschreiben Sie Pfade im Arbeitsbaum, indem Sie sie durch den Inhalt im Index oder im <baum> ersetzen." Das heißt, wenn nicht angegeben, <tree-ish>wird der Inhalt des Index zum Aktualisieren des Arbeitsbaums verwendet. Dies kann von HEAD abweichen oder nicht.
Tuntap
137

Auf Kopf zurücksetzen:

So setzen Sie eine einzelne Datei auf HEAD zurück:

git checkout @ -- myfile.ext

Beachten Sie, dass @die Abkürzung für HEAD. Eine ältere Version von git unterstützt die Kurzform möglicherweise nicht.

Auf Index zurücksetzen:

So setzen Sie eine einzelne Datei auf den Index zurück , vorausgesetzt, der Index ist nicht leer, andernfalls auf HEAD:

git checkout -- myfile.ext

Der Punkt ist, dass Sie aus@HEAD Sicherheitsgründen nicht aus dem Befehl auslassen oder ihn verlassen möchten, es sei denn , Sie möchten ausdrücklich nur auf den Index zurücksetzen .

Scharfsinn
quelle
1
Was ist mit dem "-" vor myfile.ext los?
Lance Kind
3
@LanceKind Soweit ich weiß, wird dies verwendet, um eine Liste von Dateinamen abzugrenzen, die darauf folgt. Ohne sie gibt es Fälle, in denen git die Argumente falsch interpretiert.
Acumenus
2
Nicht nur Dateinamen. Die weit verbreitete Konvention trennt Optionen von Positionsargumenten in vielen Dienstprogrammen. Siehe man bashSeite. Auch in dieser Antwort erwähnt: unix.stackexchange.com/a/187548/142855
boweeb
1
Herkömmlicherweise wird das --verwendet, um das Programm zu informieren I've finished specifying "options", and from here on, everything will be a positional argument.. Herkömmlicherweise sind "Optionen" die Token, --recursivedie in beliebiger Reihenfolge erscheinen oder sogar in ihrer Kurzform wie mit kombiniert werden können rm -rf. Im Gegenteil, "Positionsargumente" ähneln eher Argumenten, die an eine Funktion in einer Programmiersprache übergeben werden: Ihre Position in der Liste der Token definiert, was genau das Programm mit ihnen tun wird (dies sind häufig Dateinamen). --beseitigt Unklarheiten darüber, was was ist.
Iono
42

Um zu Upstream / Master zurückzukehren, gehen Sie wie folgt vor:

git checkout upstream/master -- myfile.txt
Ann Raiho
quelle
19

Seit Git 2.23 (August 2019) können Sie verwenden restore( weitere Informationen ):

git restore pathTo/MyFile

Das oben Gesagte wird MyFilebeim HEAD(letzten Commit) des aktuellen Zweigs wiederhergestellt .

Wenn Sie die Änderungen von einem anderen Commit erhalten möchten, können Sie den Commit-Verlauf rückwärts bearbeiten. Der folgende Befehl erhält MyFilezwei Commits vor dem letzten. Sie benötigen jetzt die Option -s( --source), die Sie jetzt verwenden, master~2und nicht master(die Standardoption), wenn Sie die Quelle wiederherstellen:

git restore -s master~2 pathTo/MyFile

Sie können die Datei auch von einem anderen Zweig erhalten!

git restore -s my-feature-branch pathTo/MyFile
AxeEffect
quelle
1
Der bisher einfachste Weg. Leider bekommt diese Antwort nicht genug Aufmerksamkeit.
Singrium
5

Ein Verweis auf HEAD ist nicht erforderlich.

git checkout -- file.js ist ausreichend

Emanuel Friedrich
quelle
4

Sie können den folgenden Befehl zum Zurücksetzen einer einzelnen Datei verwenden

git checkout HEAD -- path_to_file/file_name

Listen Sie alle geänderten Dateien auf, um den path_to_file/filenamefolgenden Befehl zu erhalten

git status
HariKishore
quelle
1

Sie können den folgenden Befehl verwenden:

git reset -- my-file.txt

Dadurch wird die Arbeitskopie my-file.txtbeim Hinzufügen aktualisiert .

ADDYQU
quelle
Ändert den Inhalt der geänderten Datei nicht wie gewünscht.
Rafael
Beim Hinzufügen zum Stash Haben Sie die Datei bearbeitet?
ADDYQU
1
Das ist nicht speziell der Punkt @ADDQU. Die Frage ist, wie man eine Datei "hart zurücksetzt" und nicht aus der bereitgestellten Liste entfernt.
Rafael
@ Rafael Du hast recht, aber ich möchte dich wissen lassen, dass es auch einen Weg gibt.
ADDYQU
0

Sie können den folgenden Befehl verwenden:

git checkout filename

Wenn Sie einen Zweig mit demselben Dateinamen haben, müssen Sie diesen Befehl verwenden:

git checkout -- filename
Milad Rahimi
quelle
1
Dadurch wird die Datei nicht "hart zurückgesetzt", sondern nur der Indexstatus in den Arbeitsbaum kopiert. Ein "Hard Reset" würde zuerst den Index zurücksetzen.
AH
-21

Ein einfacher, einfacher und praktischer Weg, um Sie aus dem heißen Wasser zu holen, besonders wenn Sie sich mit Git nicht so wohl fühlen:

  1. Zeigen Sie das Protokoll Ihrer Datei an

    git log myFile.js

    Commit 1023057173029091u23f01w276931f7f42595f84f Autor: kmiklas Datum: Di Aug 7 09:29:34 2018 -0400

    JIRA-12345 - Refactor mit neuer Architektur.

  2. Hinweis Hash der Datei:

    1023057173029091u23f01w276931f7f42595f84f

  3. Zeigen Sie die Datei mit dem Hash an. Stellen Sie sicher, dass es das ist, was Sie wollen:

    git show 1023057173029091u23f01w276931f7f42595f84f: ./ myFile.js

  4. Leiten Sie die Datei auf eine lokale Kopie um

    git show 1023057173029091u23f01w276931f7f42595f84f: ./ myFile.js> myFile.07aug2018.js

  5. Sichern Sie Ihre aktuelle Datei.

    cp myFile.js myFile.bak.js

  6. Öffnen Sie beide Dateien in Ihrem bevorzugten Texteditor.

    vim myFile.js
    vim myFile.07aug2018.js

  7. Kopieren Sie den Code zum Einfügen und Einfügen von myFile.07aug2018.js in myFile.js und speichern Sie ihn.

  8. Commit und Push myFile.js

  9. Zeigen Sie das Protokoll erneut an und vergewissern Sie sich, dass Ihre Datei ordnungsgemäß vorhanden ist.

  10. Bitten Sie Ihre Kunden, die neueste Version abzurufen, und beobachten Sie, wie sie mit der alten Version funktioniert.

Nicht die sexieste oder git-zentrierteste Lösung und definitiv ein "manuelles" Zurücksetzen / Umkehren, aber es funktioniert. Es erfordert nur minimale Git-Kenntnisse und stört den Commit-Verlauf nicht.

kmiklas
quelle
2
Diese Antwort ist weitaus komplexer und fehleranfälliger als alle Lösungen, die jahrelang älter waren.
Artif3x
2
Warum sollte jemand diese Lösung verwenden? Die wahre Antwort ist nur ein einfacher Befehl.
Milad Rahimi
1
Dies ist die optimale Lösung für bestimmte Umstände. Es hat Vorteile für diejenigen, die sich in einer Situation befinden, in der Git nicht richtig funktioniert, und für diejenigen, die eine Problemumgehung benötigen.
kmiklas