Arbeitskopienänderungen einer Datei in Git rückgängig machen?

1633

Nach dem letzten Festschreiben habe ich eine Reihe von Dateien in meiner Arbeitskopie geändert, aber ich möchte die Änderungen an einer dieser Dateien rückgängig machen, da beim Zurücksetzen auf den gleichen Status wie beim letzten Festschreiben.

Ich möchte jedoch nur die Änderungen an der Arbeitskopie nur dieser einen Datei rückgängig machen, sonst nichts.

Wie mache ich das?

hasen
quelle

Antworten:

2214

Sie können verwenden

git checkout -- file

Sie können dies ohne --(wie von nimrodm vorgeschlagen) tun. Wenn der Dateiname jedoch wie ein Zweig oder ein Tag (oder eine andere Revisionskennung) aussieht, kann dies zu Verwirrung führen. Daher --ist die Verwendung am besten.

Sie können auch eine bestimmte Version einer Datei auschecken:

git checkout v1.2.3 -- file         # tag v1.2.3
git checkout stable -- file         # stable branch
git checkout origin/master -- file  # upstream master
git checkout HEAD -- file           # the version from the most recent commit
git checkout HEAD^ -- file          # the version before the most recent commit
Brian Campbell
quelle
34
Was ist der Unterschied zwischen HEAD und HEAD ^?
Hasen
62
HEAD ist das letzte Commit für den aktuellen Zweig, und HEAD ^ ist das Commit davor für den aktuellen Zweig. Für die von Ihnen beschriebene Situation können Sie git checkout HEAD - Dateiname verwenden.
Paul
16
Kurz gesagt "git checkout sha-reference - Dateiname", wobei die sha-Referenz eine Referenz auf das sha eines Commits in irgendeiner Form (Zweig, Tag, Eltern usw.) ist
Lakshman Prasad
29
HINWEIS: Wenn die Datei bereits bereitgestellt ist, müssen Sie sie zuerst zurücksetzen. git reset HEAD <filename> ; git checkout -- <filename>
Olie
14
@gwho Ja, Sie können HEAD^^für 2 Commits aus dem letzten oder HEAD^^^für 3 Commits zurück tun . Sie können auch HEAD~2oder verwenden HEAD~3, was bequemer wird, wenn Sie mehr Commits zurückgeben möchten, während HEAD^2dies "das zweite übergeordnete Element dieses Commits" bedeutet. Aufgrund von Merge-Commits kann ein Commit mehr als ein vorheriges Commit haben. Mit HEAD^einer Nummer wird also ausgewählt, welches dieser Eltern verwendet wird, während mit HEAD~einer Nummer immer das erste übergeordnete Commit ausgewählt wird, aber diese Anzahl von Commits zurück. Siehe git help rev-parsefür weitere Details.
Brian Campbell
139

Benutz einfach

git checkout filename

Dadurch wird der Dateiname durch die neueste Version aus dem aktuellen Zweig ersetzt.

WARNUNG: Ihre Änderungen werden verworfen - es wird keine Sicherung gespeichert.

Nimrodm
quelle
22
@duckx dient dazu, Zweignamen von Dateinamen zu unterscheiden. Wenn Sie sagen git checkout xund x zufällig sowohl ein Zweigname als auch ein Dateiname ist, bin ich mir nicht sicher, wie das Standardverhalten lautet, aber ich denke, Git geht davon aus, dass Sie zu Zweig x wechseln möchten. Wenn Sie verwenden --, sagen Sie, dass das Folgende Dateinamen sind.
Hasen
1
ic danke, dass du das geklärt hast. Jeder geht einfach davon aus, dass Sie wissen, was - bedeutet, wenn er Ihnen Beispiele zeigt. und es ist nicht etwas, das Sie auch leicht googeln können.
Patoshi
1
Es sieht so aus, als ob die Antwort bearbeitet wurde, um --sie zu entfernen . Obwohl immer noch korrekt, wie @hasen betont, kann es bei Unklarheiten zwischen Dateinamen und Zweignamen zu sehr unerwünschtem Verhalten kommen!
BrainSlugs83
2
Ich mag es so wie es ist, ohne --, schön und einfach. Wenn Sie Zweige mit Dateinamen benennen, muss irgendwo schlecht gedacht werden ...
Marco Faustinelli
133
git checkout <commit> <filename>

Ich habe dies heute verwendet, weil mir klar wurde, dass mein Favicon vor einigen Commits überschrieben wurde, als ich auf Drupal 6.10 hochgestuft habe, also musste ich es zurückbekommen. Folgendes habe ich getan:

git checkout 088ecd favicon.ico
neoneye
quelle
1
Wie erhalte ich das Commit (einer zuvor gelöschten Datei), außer beim Scrollen, um Tonnen von "git log --stat" -Ausgabe zu werfen?
Alex
4
IMO ist es schwierig, über die Befehlszeile das Git-Protokoll zu durchsuchen und die richtige Datei zu finden. Mit einer GUI-App wie sourcetreeapp.com
neoneye
6
git log --oneline <filename>gibt Ihnen ein kompakteres Protokoll und enthält nur Änderungen an der spezifischen Datei
rjmunro
1
alternativ können Siegit reflog <filename>
ygesher
70

Wenn Ihre Datei bereits bereitgestellt ist (passiert, wenn Sie nach dem Bearbeiten der Datei ein Git hinzufügen usw.), um Ihre Änderungen aufzuheben.

Verwenden

git reset HEAD <file>

Dann

git checkout <file>

Wenn nicht bereits inszeniert, verwenden Sie einfach

git checkout <file>
thanikkal
quelle
2
Dies war hilfreicher als das akzeptierte haha. Es ist leicht zu vergessen, welche Änderungen vorgenommen wurden und welche nicht. Das Zurücksetzen hat also geholfen. Obwohl ich vorher auch "git reset --hard" ausprobiert habe, hat es nicht das getan, was "git reset HEAD" getan hat. Ich wundere mich warum?
Arman Bimatov
20

Wenn Sie nur die Änderungen des vorherigen Commits an dieser einen Datei rückgängig machen möchten, können Sie Folgendes versuchen:

git checkout branchname^ filename

Dadurch wird die Datei wie vor dem letzten Festschreiben ausgecheckt. Wenn Sie noch ein paar Commits zurückgeben möchten, verwenden Sie die branchname~nNotation.

Sykora
quelle
Dadurch werden die Änderungen nicht aus dem Commit entfernt, sondern nur der Diff auf die Version auf dem HEAD angewendet.
FernandoEscher
2
Das Originalplakat wollte zwar nur seine Änderungen an der Arbeitskopie rückgängig machen (glaube ich), aber nicht die Änderungen aus dem letzten Commit. Die Frage des Originalplakats war etwas unklar, so dass ich die Verwirrung verstehen kann.
Vielleicht nicht die Verwendung von OP, aber ich suchte nach einer Möglichkeit, meinen Zweig mit der Masterkopie zu überschreiben - dies funktioniert ganz gut beim Ersetzenbranchname^
Alex
15

Ich habe durch Git Bash fertig:

(use "git checkout -- <file>..." to discard changes in working directory)

  1. Git Status. [Wir haben also gesehen, dass eine Datei geändert wurde.]
  2. git checkout - index.html [Ich habe in der Datei index.html geändert:
  3. Git-Status [jetzt wurden diese Änderungen entfernt]

Geben Sie hier die Bildbeschreibung ein

Shiva
quelle
8

Ich bin immer verwirrt, daher hier ein Erinnerungstestfall. Nehmen wir an, wir müssen dieses bashSkript testen git:

set -x
rm -rf test
mkdir test
cd test
git init
git config user.name test
git config user.email [email protected]
echo 1 > a.txt
echo 1 > b.txt
git add *
git commit -m "initial commit"
echo 2 >> b.txt
git add b.txt
git commit -m "second commit"
echo 3 >> b.txt

An diesem Punkt wird die Änderung im Cache nicht inszeniert, so git statusist:

$ git status
On branch master
Changes not staged for commit:
  (use "git add <file>..." to update what will be committed)
  (use "git checkout -- <file>..." to discard changes in working directory)

    modified:   b.txt

no changes added to commit (use "git add" and/or "git commit -a")

Wenn wir dies tun git checkout, ist das Ergebnis:

$ git checkout HEAD -- b.txt
$ git status
On branch master
nothing to commit, working directory clean

Wenn wir es stattdessen tun git reset, ist das Ergebnis:

$ git reset HEAD -- b.txt
Unstaged changes after reset:
M   b.txt
$ git status
On branch master
Changes not staged for commit:
  (use "git add <file>..." to update what will be committed)
  (use "git checkout -- <file>..." to discard changes in working directory)

    modified:   b.txt

no changes added to commit (use "git add" and/or "git commit -a")

In diesem Fall git resetmacht es also keinen Unterschied, ob die Änderungen nicht bereitgestellt werden , während git checkoutdie Änderungen überschrieben werden.


Nehmen wir nun an, dass die letzte Änderung gegenüber dem obigen Skript inszeniert / zwischengespeichert ist, das heißt, wir haben sie auch git add b.txtam Ende vorgenommen.

In diesem Fall ist git statusan dieser Stelle:

$ git status
On branch master
Changes to be committed:
  (use "git reset HEAD <file>..." to unstage)

    modified:   b.txt

Wenn wir dies tun git checkout, ist das Ergebnis:

$ git checkout HEAD -- b.txt
$ git status
On branch master
nothing to commit, working directory clean

Wenn wir es stattdessen tun git reset, ist das Ergebnis:

$ git reset HEAD -- b.txt
Unstaged changes after reset:
M   b.txt
$ git status
On branch master
Changes not staged for commit:
  (use "git add <file>..." to update what will be committed)
  (use "git checkout -- <file>..." to discard changes in working directory)

    modified:   b.txt

no changes added to commit (use "git add" and/or "git commit -a")

In diesem Fall werden also, wenn die Änderungen git resetbereitgestellt werden, schrittweise Änderungen in nicht bereitgestellte Änderungen umgewandelt, während git checkoutdie Änderungen vollständig überschrieben werden.

sdaau
quelle
7

Diese Antwort bezieht sich auf Befehle, die zum Rückgängigmachen lokaler Änderungen erforderlich sind, die sich in mehreren spezifischen Dateien in demselben oder mehreren Ordnern (oder Verzeichnissen) befinden. Diese Antwort befasst sich speziell mit Fragen, bei denen ein Benutzer mehr als eine Datei hat, der Benutzer jedoch nicht alle lokalen Änderungen rückgängig machen möchte:

Wenn Sie eine oder mehrere Dateien haben, können Sie denselben Befehl ( git checkout -- file) auf jede dieser Dateien anwenden, indem Sie jeden ihrer Speicherorte durch Leerzeichen getrennt auflisten, wie in:

git checkout -- name1/name2/fileOne.ext nameA/subFolder/fileTwo.ext

Beachten Sie den obigen Abstand zwischen name1 / name2 / fileOne.ext nameA / subFolder / fileTwo.ext

Für mehrere Dateien im selben Ordner:

Wenn Sie Änderungen für alle Dateien in einem bestimmten Verzeichnis verwerfen müssen, verwenden Sie die Git-Kasse wie folgt:

git checkout -- name1/name2/*

Das Sternchen oben führt den Trick aus, alle Dateien an diesem Speicherort unter name1 / name2 rückgängig zu machen.

In ähnlicher Weise kann Folgendes Änderungen in allen Dateien für mehrere Ordner rückgängig machen:

git checkout -- name1/name2/* nameA/subFolder/*

Beachten Sie erneut den Abstand zwischen name1 / name2 / * nameA / subFolder / * oben.

Hinweis: name1, name2, nameA, subFolder - Alle diese Beispielordnernamen geben den Ordner oder das Paket an, in dem sich die betreffenden Dateien möglicherweise befinden.

Nirmal
quelle
5

Ich stelle meine Dateien mit der SHA-ID wieder her git checkout <sha hash id> <file name>

Sein zu
quelle
3

Für mich hat nur dieser funktioniert

git checkout -p filename

Geben Sie hier die Bildbeschreibung ein

Ramesh Bhupathi
quelle
2

Wenn Sie Ihr Commit noch nicht gepusht oder anderweitig geteilt haben:

git diff --stat HEAD^...HEAD | \
fgrep filename_snippet_to_revert | cut -d' ' -f2 | xargs git checkout HEAD^ --
git commit -a --amend
Jesse Glick
quelle
0

Wenn es bereits festgeschrieben ist, können Sie die Änderung für die Datei zurücksetzen und erneut festschreiben und dann das neue Festschreiben mit dem letzten Festschreiben quetschen.

Gina
quelle
1
Das Hinzufügen spezifischer Befehle würde dem Originalposter und zukünftigen Besuchern helfen.
Adrian
0

Ich weiß nicht warum, aber wenn ich versuche, meinen Code einzugeben, wird er als Bild angezeigt.

Geben Sie hier die Bildbeschreibung ein

Gen
quelle