Wie kann ich eine einzelne Datei aus einer bestimmten Version in Git abrufen?

831

Ich habe ein Git-Repository und möchte sehen, wie einige Dateien vor einigen Monaten ausgesehen haben. Ich fand die Überarbeitung zu diesem Zeitpunkt; es ist 27cf8e84bb88e24ae4b4b3df2b77aab91a3735d8. Ich muss sehen, wie eine Datei aussieht, und sie auch als ("neue") Datei speichern.

Ich habe es geschafft, die Datei mit zu sehen gitk, aber es gibt keine Option zum Speichern. Ich habe es mit Befehlszeilentools versucht. Das nächste, was ich bekam, war:

git-show 27cf8e84bb88e24ae4b4b3df2b77aab91a3735d8 my_file.txt

Dieser Befehl zeigt jedoch einen Unterschied und nicht den Dateiinhalt. Ich weiß, dass ich später so etwas wie eine PAGER=catAusgabe verwenden und in eine Datei umleiten kann, aber ich weiß nicht, wie ich zum eigentlichen Dateiinhalt komme.

Grundsätzlich suche ich so etwas wie svn cat .

Milan Babuškov
quelle
73
Der Schlüssel hier: git show(nicht hilfreich) verwendet eine andere Syntax mit einem Doppelpunkt. git show 2c7cf:my_file.txt
Steve Bennett
4
Zur weiteren Verdeutlichung fordert der obige Befehl git auf, zwei separate Objekte anzuzeigen, eine Revision und eine Datei. Die unten akzeptierte Antwort, bei der ein Doppelpunkt zwischen den beiden Elementen verwendet wird, fordert bei einer bestimmten Revision eine bestimmte Datei an.
Jhclark
2
Auf * nix brauchst du kein PAGER, nur Shell-Umleitung mit>
Konstantin Pelepelin
Mögliches Duplikat von Gibt es einen schnellen git-Befehl, um eine alte Version einer Datei anzuzeigen?
Ciro Santilli 法轮功 病毒 审查 六四 事件 10
Checat hat einen wichtigen Kommentar für diejenigen, die den Inhalt in eine Datei exportieren möchten. Sie brauchen etwas wie folgt aus : git show {sha}: my_file.txt> old_my_file.txt
Ormurin

Antworten:

743

Um Ihre eigene Antwort zu vervollständigen, lautet die Syntax in der Tat

git show object
git show $REV:$FILE
git show somebranch:from/the/root/myfile.txt
git show HEAD^^^:test/test.py

Der Befehl verwendet den üblichen Revisionsstil, dh Sie können eine der folgenden Optionen verwenden:

  1. Zweignamen (wie vorgeschlagen durch Asche )
  2. HEAD+ x Anzahl der ^Zeichen
  3. Der SHA1-Hash einer bestimmten Revision
  4. Die ersten paar (vielleicht 5) Zeichen eines bestimmten SHA1-Hash

Tipp Beachten Sie, dass Sie bei Verwendung von " git show" immer einen Pfad aus dem Stammverzeichnis des Repositorys angeben müssen , nicht Ihre aktuelle Verzeichnisposition.

(Obwohl Mike Morearty erwähnt, dass Sie zumindest mit git 1.7.5.4 einen relativen Pfad angeben können, indem Sie " ./" am Anfang des Pfads einfügen - zum Beispiel:

git show HEAD^^:./test.py

)


Mit Git 2.23+ (August 2019) können Sie auch den verwirrenden Befehlgit restore ersetzengit checkout

git restore -s <SHA1>     -- afile
git restore -s somebranch -- afile

Das würde im Arbeitsbaum nur die Datei wiederherstellen, die in der "source" ( -s) - Festschreibung von SHA1 oder Zweig vorhanden ist somebranch.
So stellen Sie auch den Index wieder her:

git restore -s <SHA1> -SW -- afile

( -SW: kurz für --staged --worktree)


Vor git1.5.x wurde dies mit einigen Sanitärinstallationen durchgeführt:

git ls-tree <rev>
Zeigen Sie eine Liste eines oder mehrerer "Blob" -Objekte innerhalb eines Commits an

git cat-file blob <file-SHA1>
cat eine Datei, wie sie innerhalb einer bestimmten Revision festgeschrieben wurde (ähnlich wie bei svn cat). Verwenden Sie git ls-tree, um den Wert einer bestimmten Datei-sha1 abzurufen

git cat-file -p $(git-ls-tree $REV $file | cut -d " " -f 3 | cut -f 1)::

git-ls-tree listet die Objekt-ID für $ file in Revision $ REV auf. Diese wird aus der Ausgabe herausgeschnitten und als Argument für git-cat-file verwendet, die eigentlich als git-cat-object bezeichnet werden sollte, und wird einfach ausgegeben das Objekt zu stdout.


Hinweis: Seit Git 2.11 (Q4 2016) können Sie einen Inhaltsfilter auf die git cat-fileAusgabe anwenden !

Siehe Commit 3214594 , Commit 7bcf341 ( 09.09.2016 ), Commit 7bcf341 ( 09.09.2016 ) und Commit b9e62f6 , Commit 16dcc29 (24. August 2016) von Johannes Schindelin ( dscho) .
(Zusammengeführt von Junio ​​C Hamano - gitster- in Commit 7889ed2 , 21. September 2016)

cat-file: support --textconv/ --filtersim Batch-Modus

Obwohl " git hash-objects", ein Tool zum Aufnehmen eines Datenstroms im Dateisystem, der in den Git-Objektspeicher gestellt wird, die Konvertierungen von "Außenwelt zu Git" (z. B. Konvertierungen am Ende der Zeile und Anwendung) durchführen darf des Clean-Filters), und die Funktion war von Anfang an standardmäßig aktiviert. Bei der umgekehrten Operation " git cat-file", bei der ein Objekt aus dem Git-Objektspeicher entnommen und für den Verbrauch durch die Außenwelt ausgelagert wird, fehlte ein gleichwertiger Mechanismus Führen Sie die "Git-to-Outside-World"

git config diff.txt.textconv "tr A-Za-z N-ZA-Mn-za-m <"
git cat-file --textconv --batch

Hinweis: " git cat-file --textconv" hat vor kurzem (2017) mit dem Segfaulting begonnen, was in Git 2.15 (Q4 2017) korrigiert wurde.

Siehe Commit cc0ea7c (21. September 2017) von Jeff King ( peff) .
(Zusammengeführt von Junio ​​C Hamano - gitster- in Commit bfbc2fc , 28. September 2017)


Beachten Sie, dass Sie zum Überschreiben / Ersetzen einer Datei durch einen früheren Inhalt den verwirrenden git checkoutBefehl nicht mehr verwenden sollten, sondern git restore(Git 2.23+, August 2019).

git restore -s <SHA1> -- afile

Das würde im Arbeitsbaum nur die Datei wiederherstellen, die im "source" ( -s) Commit SHA1 vorhanden ist.
So stellen Sie auch den Index wieder her:

git restore -s <SHA1> -SW -- afile

( -SW: kurz für --staged --worktree)

VonC
quelle
6
@Oscar Da git showder Inhalt im Wesentlichen auf der stdout(Standardausgabe) ausgegeben wird, können Sie diese Ausgabe einfach in eine beliebige Datei umleiten ( tldp.org/LDP/abs/html/io-redirection.html ).
VonC
8
git checkout [branch | revision] filepathist der richtige Befehl
Gaui
12
@Gaui git checkoutwürde aber Ihre Datei durch eine andere Version überschreiben , im Gegensatz zu git show, wodurch Sie sie unter einem anderen Namen speichern können, damit Sie beide (die aktuelle Version und die alte Version) erhalten und sehen können . Aus der Frage geht nicht hervor, ob das OP seine aktuelle Version durch eine alte ersetzen möchte .
VonC
9
Ich möchte darauf hinweisen, dass ^^^dies auch allgemeiner als ~~~oder besser geschrieben werden kann ~3. Die Verwendung von Tildes hat auch den Vorteil, dass der Dateinamenabgleich einiger Shells (z. B. zsh) nicht ausgelöst wird.
Eric O Lebigot
2
Ich habe kein ausreichend altes Git, um zu überprüfen: Behandelt Pre-1.5.x git rev-parsedie rev:pathSyntax? (In einem neueren Git können Sie git cat-file -p $REV:path. Funktioniert jedoch auch git showfür Verzeichnispfade, so dass es nicht nur kürzer ist, sondern normalerweise näher an dem, was man will.)
Torek
510

Wenn Sie den Inhalt einer Datei in Ihrem aktuellen Zweig durch den Inhalt der Datei aus einem vorherigen Commit oder einem anderen Zweig ersetzen / überschreiben möchten , können Sie dies mit den folgenden Befehlen tun:

git checkout 08618129e66127921fbfcbc205a06153c92622fe path/to/file.txt

oder

git checkout mybranchname path/to/file.txt

Sie müssen diese Änderungen dann festschreiben, damit sie in der aktuellen Branche wirksam werden.

ca.
quelle
4
Die einfachste Lösung, für die git-checkout entwickelt wurde. Wenn Sie den Pfadnamen angeben, wird nur die passende Datei ausgecheckt. Von git-checkout
manpage
1
Wie kehren Sie dann zum vorherigen Status zurück, bevor Sie diesen Befehl ausführen?
Flint
@Flint Wenn Sie aus dem HEAD-Status kommen, ist dies so einfach wie das Auschecken von git HEAD - [vollständiger Pfad].
Tiago Espinha
72
Beachten Sie, dass dadurch die vorhandene Datei in diesem Pfad überschrieben wird, während die git show SHA1:PATHLösung nur in stdout gedruckt wird.
Flimm
Nett! Ich hätte das nicht durch einen Blick herausfinden können git help checkout. Ich musste ab einem bestimmten Datum ein Unterverzeichnis git checkout @{YYYY-MM-DD} sub-dir
auschecken
150

Sie müssen den vollständigen Pfad zur Datei angeben:

git show 27cf8e84bb88e24ae4b4b3df2b77aab91a3735d8:full/repo/path/to/my_file.txt
Milan Babuškov
quelle
7
muss nicht der volle Weg sein. Pfad vom Git-Stammverzeichnis (diejenigen, die hereinkamen, git show --name-onlysind auch genug
Mohsen
7
Ähm, vollständiger Pfad vom Repository-Stamm. Schauen Sie sich das Beispiel genauer an, das ich gegeben habe. Es gibt keinen führenden Schrägstrich vor "voll".
Milan Babuškov
7
Zu Ihrer Information, wenn Sie sich in einem Unterverzeichnis befinden, können Sie ./filename.ext auch erfolgreich verwenden.
Reisender
Ich denke, der Punkt ist, wenn Sie dabei sind full/repo/path/tound es versuchen : git show 27cf8e84:my_file.txt, werden Sie mit einer Nachricht belohnt wie: fatal: Pfad 'full / repo / path / to / my_file.txt' existiert, aber nicht 'my_file.txt' . Meinten Sie '27cf8e84: full / repo / path / to / my_file.txt' aka '27cf8e84: ./ my_file.txt'? Es ist so, als hätte Git direkt helfen können, aber er hat sich entschieden, hier pedantisch zu sein.
Ed Randall
101

Der einfachste Weg ist zu schreiben:

git show HASH:file/path/name.ext > some_new_name.ext

wo:

  • HASH ist die Git-Revisions-SHA-1-Hash-Nummer
  • file / path / name.ext ist der Name der gesuchten Datei
  • some_new_name.ext ist Pfad und Name, in dem die alte Datei gespeichert werden soll

Beispiel

git show 27cf8e84bb88e24ae4b4b3df2b77aab91a3735d8:my_file.txt > my_file.txt.OLD

Dadurch wird my_file.txt aus Revision 27cf8e als neue Datei mit dem Namen my_file.txt.OLD gespeichert

Es wurde mit Git 2.4.5 getestet.

Wenn Sie gelöschte Dateien abrufen möchten, können Sie diese verwenden HASH~1(ein Commit vor dem angegebenen HASH).

BEISPIEL:

git show 27cf8e84bb88e24ae4b4b3df2b77aab91a3735d8~1:deleted_file.txt > deleted_file.txt
jmarceli
quelle
1
Zusätzliche Informationen: Sie können den HASH zB mit git log
xotix
@xotix Danke. Ich habe die ganze Geschichte HASH für eine bestimmte Dateigit log file/path/name.ext
Sriram Kannan
11

In Windows mit Git Bash:

  • Ändern Sie in Ihrem Arbeitsbereich das Verzeichnis in den Ordner, in dem sich Ihre Datei befindet
  • git show cab485c83b53d56846eb883babaaf4dff2f2cc46:./your_file.ext > old.ext
Alessandro Jacopson
quelle
8

Und um es schön in eine Datei zu kopieren (zumindest unter Windows) - Git Bash:

$ echo "`git show 60d8bdfc:src/services/LocationMonitor.java`" >> LM_60d8bdfc.java

Die "Anführungszeichen werden benötigt, damit Zeilenumbrüche erhalten bleiben.

Mr_and_Mrs_D
quelle
Schön. +1. Gute Ergänzung zu der git showoben erwähnten Syntax.
VonC
23
Ich verstehe wirklich nicht, warum Sie Echo mit oder ohne Anführungszeichen verwenden würden. Und ich verstehe nicht, warum Sie die angehängte Form der Ausgabeumleitung wünschen würden. Wäre es nicht besser, einfach zu schreiben: git show 60d8bdfc: src / services / LocationMonitor.java> LM_60d8bdfc.java Wenn Sie aus irgendeinem Grund tatsächlich Zeilenenden im Dos-Stil erzwingen möchten, können Sie sie durch unix2dos leiten. Aber ich habe es nie als am wenigsten nützlich empfunden, dos-Zeilenenden unter Windows beizubehalten, da alle anderen Textwerkzeuge als der Notizblock, die ich unter Windows verwendet habe, Zeilen im Unix-Stil problemlos verarbeiten können.
Sootsnoot
4
git show 60d8bdfc: src / services / LocationMonitor.java >> LM_60d8bdfc.java hat für mich gearbeitet.
Mike6679
@ Mike: Bist du auf Windows?
Mr_and_Mrs_D
2
Verwenden Sie keine doppelten Anführungszeichen, da Ihre Dateizeichen, die wie eine Shell-Variable aussehen, dh $ LANG, ersetzt werden. @ LưuVĩnhPhúc spart. auch nicht verwenden >> Es wird die Datei anhängen, wenn es existiert und könnte zu Fehlern führen
theguy
3

Auf diese Weise können Sie alle gelöschten Dateien zwischen Commits abrufen, ohne den Pfad anzugeben. Dies ist hilfreich, wenn viele Dateien gelöscht wurden.

git diff --name-only --diff-filter=D $commit~1 $commit | xargs git checkout $commit~1
Adrian Gunawan
quelle
1
git checkout {SHA1} -- filename

Dieser Befehl ruft die kopierte Datei von einem bestimmten Commit ab.

jsina
quelle
-2

Rufen Sie die Datei aus einem vorherigen Commit ab, indem Sie das vorherige Commit auschecken und die Datei kopieren.

  • Beachten Sie, auf welchem ​​Zweig Sie sich befinden: Git-Zweig
  • Überprüfen Sie das vorherige Commit, das Sie möchten: git checkout 27cf8e84bb88e24ae4b4b3df2b77aab91a3735d8
  • Kopieren Sie die gewünschte Datei an einen temporären Speicherort
  • Überprüfen Sie den Zweig, von dem aus Sie gestartet sind: git checkout theBranchYouNoted
  • Kopieren Sie die Datei, die Sie an einem temporären Speicherort abgelegt haben
  • Übernehmen Sie Ihre Änderung an git: git commit -m "added file ?? from previous commit"
rocketInABog
quelle