it-swarm.com.de

Zurücksetzen einer einzelnen Datei auf eine frühere Version in Git

Gibt es eine Möglichkeit, verschiedene Commits für eine Datei durchzuführen? Angenommen, ich habe eine Datei 5-mal geändert und möchte zurück zu Änderung 2, nachdem ich bereits ein Commit ausgeführt und in ein Repository verschoben habe.

Nach meinem Verständnis besteht der einzige Weg darin, viele Zweige zu behalten. Habe ich das richtig verstanden? Wenn ich recht habe, werde ich in ein paar Tagen Hunderte von Filialen haben, also verstehe ich es wahrscheinlich nicht wirklich.

Könnte jemand das bitte klären?

554
georgeliquor

Beginnen wir mit einer qualitativen Beschreibung dessen, was wir tun möchten (viel davon steht in der Antwort von Ben Straub). Wir haben eine Reihe von Commits durchgeführt, von denen fünf eine bestimmte Datei geändert haben, und wir möchten die Datei auf eine der vorherigen Versionen zurücksetzen. Erstens speichert git keine Versionsnummern für einzelne Dateien. Es verfolgt nur den Inhalt - ein Commit ist im Wesentlichen eine Momentaufnahme des Arbeitsbaums, zusammen mit einigen Metadaten (z. B. eine Commit-Nachricht). Wir müssen also wissen, welches Commit die Version der gewünschten Datei hat. Sobald wir das wissen, müssen wir ein neues Commit ausführen, um die Datei auf diesen Zustand zurückzusetzen. (Wir können nicht nur mit der Geschichte herumspielen, weil wir diese Inhalte bereits gepusht haben und die Bearbeitung der Geschichte mit allen anderen durcheinander gebracht hat.)

Beginnen wir also damit, das richtige Commit zu finden. Sie können die Festschreibungen, die Änderungen an bestimmten Dateien vorgenommen haben, sehr leicht sehen:

git log path/to/file

Wenn Ihre Commit-Nachrichten nicht gut genug sind und Sie sehen müssen, was mit der Datei in jedem Commit geschehen ist, verwenden Sie die Option -p/--patch:

git log -p path/to/file

Oder wenn Sie die grafische Ansicht von gitk bevorzugen

gitk path/to/file

Sie können dies auch tun, wenn Sie gitk über das Ansichtsmenü gestartet haben. Eine der Optionen für eine Ansicht ist eine Liste der einzuschließenden Pfade.

In beiden Fällen können Sie den SHA1 (Hash) des Commits mit der gewünschten Dateiversion ermitteln. Jetzt müssen Sie nur noch Folgendes tun:

# get the version of the file from the given commit
git checkout <commit> path/to/file
# and commit this modification
git commit

(Mit dem Befehl checkout wird die Datei zuerst in den Index eingelesen und dann in den Arbeitsbaum kopiert. Daher muss sie zur Vorbereitung des Commits nicht mit git add zum Index hinzugefügt werden.)

Wenn Ihre Datei möglicherweise keinen einfachen Verlauf hat (z. B. Umbenennen und Kopieren), lesen Sie VonCs hervorragenden Kommentar. git kann angewiesen werden, auf Kosten der Geschwindigkeit sorgfältiger nach solchen Dingen zu suchen. Wenn Sie sicher sind, dass die Geschichte einfach ist, brauchen Sie sich nicht darum zu kümmern.

797
Cascabel

Git ist sehr flexibel. Sie sollten nicht Hunderte von Filialen benötigen, um das zu tun, was Sie verlangen. Wenn Sie den Status bis zur 2. Änderung zurücksetzen möchten (und es sich tatsächlich um eine Änderung handelt, die bereits festgeschrieben und verschoben wurde), verwenden Sie git revert . So etwas wie:

_git revert a4r9593432 
_

dabei steht a4r9593432 für die Anfangszeichen des Hashs des Commits, den Sie zurücksetzen möchten.

Wenn das Commit Änderungen an vielen Dateien enthält, Sie jedoch nur eine der Dateien wiederherstellen möchten, können Sie git reset (die 2. oder 3. Form) verwenden:

_git reset a4r9593432 -- path/to/file.txt
# the reverted state is added to the staging area, ready for commit
git diff --cached path/to/file.txt        # view the changes
git commit
git checkout HEAD path/to/file.txt        # make the working tree match HEAD           
_

Aber das ist ziemlich komplex und das Zurücksetzen von Git ist gefährlich. Verwenden Sie stattdessen _git checkout <hash> <file path>_, wie Jefromi vorschlägt.

Wenn Sie nur anzeigen möchten, wie die Datei in commit x aussah, können Sie git show verwenden:

_git show a4r9593432:path/to/file.txt
_

Für alle Befehle gibt es viele Möglichkeiten, auf ein Commit zu verweisen, außer über den Commit-Hash (siehe Commits benennen im Git-Benutzerhandbuch).

71
Jim Hurne

Git denkt nicht in Dateiversionen. Eine Version in Git ist eine Momentaufnahme des gesamten Baums.

Vor diesem Hintergrund möchten Sie wirklich einen Baum, der den neuesten Inhalt der meisten Dateien enthält, wobei der Inhalt einer Datei jedoch derselbe ist wie vor 5 Commits. Dies erfolgt in Form eines neuen Commits über die alten, und die neueste Version des Baums hat das, was Sie wollen.

Ich weiß nicht, ob es einen Einzeiler gibt, der eine einzelne Datei auf den Inhalt von vor 5 Commits zurücksetzt, aber die Lo-Fi-Lösung sollte funktionieren: checkout master~5, kopiere die Datei an eine andere Stelle, checkout master, kopieren Sie die Datei zurück und bestätigen Sie sie.

7
Ben Straub

Sie können ein Diff nehmen, das die gewünschten Änderungen rückgängig macht, und das festschreiben.

Z.B. Wenn Sie die Änderungen im Bereich from..to rückgängig machen möchten, gehen Sie wie folgt vor

git diff to..from > foo.diff  # get a reverse diff
patch < foo.diff
git commit -a -m "Undid changes from..to".
5
Alex Budovski

Von hier extrahiert: http://git.661346.n2.nabble.com/Revert-a-single-commit-in-a-single-file-td6064050.html

 git revert <commit> 
 git reset 
 git add <path> 
 git commit ... 
 git reset --hard # making sure you didn't have uncommited changes earlier 

Es hat sehr gut funktioniert.

4
Felipe