Änderungen an einer Datei in einem Commit zurücksetzen

126

Ich möchte Änderungen, die durch ein bestimmtes Commit vorgenommen wurden, nur auf eine bestimmte Datei zurücksetzen.

Kann ich dafür den Befehl git revert verwenden?

Irgendeine andere einfache Möglichkeit, dies zu tun?

Lakshman Prasad
quelle
Seltsam ... warum die Veränderung nach all den Jahren?
VonC

Antworten:

222

Der sauberste Weg, den ich gesehen habe, wird hier beschrieben

git show some_commit_sha1 -- some_file.c | git apply -R

Ähnlich wie bei VonCs Antwort, jedoch mit git showund git apply.

mgalgs
quelle
10
Schön gemacht. Die Skriptlösung ist dafür übertrieben. Warum kann es nicht einfach einen Git-Revert-Sha-1-Dateinamen geben?
Mark Edington
16
Dies funktioniert auf meinem Mac, aber unter Windows (unter Cygwin) gibt es mir:fatal: unrecognized input
Kedar Mhaswade
1
@ MerhawiFissehaye: Ich denke, Git Checkout wird die Änderungen nur wieder zurücksetzen, um auf den Zustand zurückzugreifen, der festgeschrieben wurde. Ich habe den Dateinamen hinzugefügt. git commit --amend ', um die Datei aus dem Commit zu entfernen.
ViFI
3
Nur ein Tipp, ich muss fast immer das -3Flag hinzufügen , damit git für eine Drei-Wege-Zusammenführung gilt, wenn der Patch fehlschlägt, da ich normalerweise eine Änderung etwas früher korrigiere.
Angularsen
2
Vielleicht für die meisten offensichtlich, aber stellen Sie sicher, dass some_file.cder Pfad zur Datei enthalten ist, wenn es einen gibt, sonst werden Sie stillschweigend nichts patchen :)
Warpling
35

Angenommen, es ist in Ordnung, den Festschreibungsverlauf zu ändern, finden Sie hier einen Workflow zum Zurücksetzen von Änderungen in einer einzelnen Datei in einem früheren Festschreiben:

Beispielsweise möchten Sie Änderungen in 1 Datei ( badfile.txt) in Festschreiben zurücksetzen aaa222:

aaa333 Good commit
aaa222 Problem commit containing badfile.txt
aaa111 Base commit

Starten Sie das Basis-Commit neu, ändern Sie das Problem-Commit und fahren Sie fort.

1) Starten Sie die interaktive Rebase:

git rebase -i aaa111

2) Markieren Sie das Problem-Commit für die Bearbeitung im Editor, indem Sie pickzu e(zur Bearbeitung) wechseln :

e aaa222
pick aaa333

3) Änderungen an der fehlerhaften Datei rückgängig machen:

git show -- badfile.txt | git apply -R

4) Fügen Sie die Änderungen hinzu und ändern Sie das Commit:

git add badfile.txt
git commit --amend

5) Beenden Sie die Rebase:

git rebase --continue
Tee
quelle
Ich möchte nur darauf hinweisen, dass dies voraussetzt, dass Sie den Git-Verlauf bearbeiten können. Einige der obigen Antworten erstellen ein neues Commit, das die bestimmte Änderung rückgängig macht, ohne den Verlauf zu bearbeiten, was nicht immer möglich / zulässig ist.
Angularsen
Fantastisch. Genau das habe ich gesucht. Ich hatte diese Idee bereits, war aber beim interaktiven Rebase verwirrt, dass die Dateien beim Ausführen editnicht als geändert angezeigt wurden . Aber das git show -- badfile.txt | git apply -Rgab die Antwort, die ich brauchte <3
mraxus
Wenn ich diesen Git-Apply--R verstehe, wird das Commit für diese Datei entfernt und auf den ursprünglich geänderten Status zurückgesetzt.
DaImTo
19

git revert ist für alle Dateiinhalte innerhalb eines Commits.

Für eine einzelne Datei können Sie ein Skript erstellen :

#!/bin/bash

function output_help {
    echo "usage: git-revert-single-file <sha1> <file>"
}

sha1=$1
file=$2

if [[ $sha1 ]]; then
git diff $sha1..$sha1^ -- $file | patch -p1
else
output_help
fi

(Aus den Git-Shell-Scripts- Dienstprogrammen von smtlaissezfaire )


Hinweis:

Ein anderer Weg wird hier beschrieben, wenn Sie Ihre aktuelle Änderung noch nicht festgeschrieben haben.

git checkout -- filename

git checkout hat einige Optionen für eine Datei, ändert die Datei von HEAD und überschreibt Ihre Änderung.


Dropped.on.Caprica erwähnt in den Kommentaren :

Sie können git einen Alias ​​hinzufügen, damit Sie git revert-file <hash> <file-loc>diese bestimmte Datei zurücksetzen können.
Sehen Sie diesen Kern .

[alias]
  revert-file = !sh /home/some-user/git-file-revert.sh
VonC
quelle
Um der Diskussion hier etwas hinzuzufügen, können Sie git einen Alias ​​hinzufügen, damit Sie git revert-file <hash> <file-loc>diese bestimmte Datei zurücksetzen können. Ich habe diese Antwort aufgehoben (obwohl ich einige Änderungen vornehmen musste, um richtig zu funktionieren). Eine Kopie meines .gitconfigund des bearbeiteten Skripts finden Sie hier: gist.github.com/droppedoncaprica/5b67ec0021371a0ad438
AlbertEngelB
@ Dropped.on.Caprica guter Punkt. Ich habe es in die Antwort für mehr Sichtbarkeit aufgenommen.
VonC
12

Ich würde einfach die --no-commitOption verwenden, git-revertum die Dateien, die Sie nicht zurücksetzen möchten, aus dem Index zu entfernen, bevor ich sie endgültig festschreibe. Hier ist ein Beispiel, das zeigt, wie Sie einfach nur die Änderungen an foo.c im zweitletzten Commit zurücksetzen können:

$ git revert --no-commit HEAD~1
$ git reset HEAD
$ git add foo.c
$ git commit -m "Reverting recent change to foo.c"
$ git reset --hard HEAD

Das erste git-reset"Staging" aller Dateien, so dass wir dann nur die eine Datei wieder hinzufügen können, die zurückgesetzt werden soll. Das Finale entfernt git-reset --harddie verbleibenden Dateiwiederherstellungen, die wir nicht behalten möchten.

Dan Moulding
quelle
9

Viel einfacher:

git reset HEAD^ path/to/file/to/revert

dann

git commit --amend   

und dann

git push -f

Die Datei ist verschwunden und Commit-Hash, Nachricht usw. sind identisch.

Wald
quelle
Benötigen Sie der Vollständigkeit halber einen git checkout -- path/to/file/to/revertSchritt? Es ist auch nicht wahr, dass der Hash danach der gleiche ist, oder? Der letzte Satz könnte besser sein als: "Das Ergebnis ist, dass das letzte Commit durch ein neues ersetzt wird, das sich nur dadurch unterscheidet, dass es die Änderungen an der zurückgesetzten Datei nicht enthält."
Kevin
@ Kevin du hast wahrscheinlich recht. Ich muss diese letzte Zeile noch einmal überprüfen, aber wenn ich auf ein paar Jahre zurückblicke, wäre ich überrascht, wenn der Commit-Hash unverändert bleibt.
Forrest
6
git reset HEAD^ path/to/file/to/revert/in/commit

Der obige Befehl entfernt die Datei aus dem Commit, spiegelt sich jedoch in wider git status.

git checkout path/to/file/to/revert/in/commit

Der obige Befehl setzt die Änderungen zurück (als Ergebnis erhalten Sie die gleiche Datei wie HEAD).

git commit

(Pass --amendzur Änderung des Commits.)

git push

Damit wird die Datei, die sich bereits im Commit befindet, entfernt und zurückgesetzt.

Die obigen Schritte sollten von dem Zweig aus ausgeführt werden, in dem das Commit ausgeführt wird.

Bharath TS
quelle
5

Sie können wie folgt vorgehen:

  1. git revert -n <*commit*>( -nAlle Änderungen rückgängig machen, aber nicht festschreiben)
  2. git add <*filename*> (Name der Datei (en), die Sie zurücksetzen und festschreiben möchten)
  3. git commit -m 'reverted message' (Nachricht zum Zurücksetzen hinzufügen)
  4. Verwerfen Sie nach dem Festschreiben die Änderungen der anderen Dateien, damit die Dateien mit den Änderungen, die Sie vor dem Zurücksetzen festgeschrieben haben, auf dem neuesten Stand bleiben
Imran Sahil
quelle
1

Wenn Sie die Änderungen an einer Datei aus Ihrem letzten Commit zurücksetzen möchten, verwende ich diese normalerweise. Ich denke, das ist die einfachste Lösung.

Bitte beachten Sie, dass die Datei dem Staging-Bereich hinzugefügt wird.

git checkout <prev_commit_hash> -- <path_to_your_file>

Ich hoffe es hilft :)

Gabeeka
quelle