Gibt es einen schnellen Git-Befehl, um eine alte Version einer Datei anzuzeigen?

1509

Gibt es in Git einen Befehl zum Anzeigen (entweder in stdout oder in $PAGERoder $EDITOR) einer bestimmten Version einer bestimmten Datei?

Mike
quelle
Wenn Sie zu dieser Frage gekommen sind, weil Sie eine ältere Version einer Binärdatei (z. B. ein Bild) überprüfen möchten, sollten Sie das alte Commit besser auschecken, sehen, was Sie sehen müssen, und dann zum HEAD zurückkehren. Dafür tun git checkout <sha1-of-the-commit-you-need>, danachgit checkout HEAD
Homero Esmeraldo

Antworten:

1730

Sie können git showmit einem Pfad aus dem Stammverzeichnis des Repositorys ( ./oder ../für die relative Pfadbildung) Folgendes verwenden:

$ git show REVISION:path/to/file

Durch REVISIONIhre tatsächliche Revision ersetzen (kann ein Git-Commit-SHA, ein Tag-Name, ein Zweigname, ein relativer Commit-Name oder eine andere Methode zum Identifizieren eines Commits in Git sein).

<repository-root>/src/main.cVerwenden Sie beispielsweise Folgendes, um die Version der Datei von vor 4 Commits anzuzeigen :

$ git show HEAD~4:src/main.c

Git für Windows erfordert Schrägstriche auch in Pfaden relativ zum aktuellen Verzeichnis. Weitere Informationen finden Sie in der Manpage für git-show.

Mipadi
quelle
5
Das scheint eigentlich nicht zu funktionieren - hast du es versucht? Für "git show HEAD: path / to / file.c" erhalte ich den Fehler "mehrdeutiges Argument".
Mike
2
Muss
20
Wenn Sie unter Windows arbeiten, kann dies ein Pfadtrennzeichen sein. Wenn ich HEAD: dir \ subdir \ file zeige, erhalte ich das anbiguous-Argument. Wenn ich HEAD zeige: dir / subdir / file, funktioniert es wie erwartet.
Matt McMinn
12
Der Pfad, den Sie nach dem: angeben müssen, stammt aus dem Stammverzeichnis des Git-Repositorys. (Dies wurde unten als Antwort gegeben, aber ich denke, es war als Kommentar zu dieser Antwort gedacht)
MatrixFrog
9
Wenn Sie es in einem Vim-Split sehen möchten, damit sie zusammen scrollen, habe ich einen kurzen Blog-Beitrag geschrieben, der zeigt, wie das geht.
Flaviu
257

Dies nach Datum zu tun sieht folgendermaßen aus:

git show HEAD@{2013-02-25}:./fileInCurrentDirectory.txt

Beachten Sie, dass HEAD@{2013-02-25}in diesem Repository (unter Verwendung des Reflogs ) "wo HEAD am 25.02.2013 war" bedeutet , nicht "das letzte Commit vor dem 25.02.2013 in diesem Zweig in der Geschichte".

Jim Hunziker
quelle
5
Genial. Spart mir viel Zeit, anstatt zum Github zu gehen und mir das Commit anzusehen.
Fizer Khan
Der "Punkt" auf dem Dateipfad war mein Problem. Vielen Dank!
Tomascharad
5
Dieser Befehl ist nützlich mit masterstatt HEAD@{2013-02-25}, wenn Sie auf einem Zweig sind
Funroll
1
Können Sie die Zeit à la git log --since='2016-04-28 23:59:59 +0100'angeben?
Dumbledad
7
Die Tatsache, dass diese Syntax das Reflog verwendet, ist wichtig und sollte stark hervorgehoben werden, da das Reflog nicht alle Commits enthält . Siehe blog.endpoint.com/2014/05/git-checkout-at-specific-date.html
Alice Heaton
113

Wenn Sie GUIs mögen, können Sie gitk verwenden:

  1. starte gitk mit:

    gitk /path/to/file
    
  2. Wählen Sie die Revision im oberen Teil des Bildschirms, z. B. nach Beschreibung oder Datum. Standardmäßig zeigt der untere Teil des Bildschirms den Unterschied für diese Revision (entsprechend dem Optionsfeld "Patch").

  3. So zeigen Sie die Datei für die ausgewählte Revision an:

    • Klicken Sie auf das Optionsfeld "Baum". Dadurch wird das Stammverzeichnis des Dateibaums bei dieser Revision angezeigt.
    • Drilldown zu Ihrer Datei.
Trausti Kristjansson
quelle
7
Dies funktioniert auch mit tig , einem verfluchten Git-Repo-Viewer.
Matthew G
1
@ Paul Slocum: Möglicherweise, weil dieser Befehl kein herkömmlicher Befehl ist, nicht der eingebaute Git. Ich denke, dieser Befehl funktioniert nur für Windows.
Envil
Beachten Sie, dass dies nur zu funktionieren scheint, wenn Sie vom Stammverzeichnis Ihres Git-Repositorys ausgehen.
Marc
Wenn Sie mit gitk gegen eine bestimmte Revision prüfen möchten, können Sie auch diese Verknüpfung verwenden : gitk REVISION /path/to/file. Dies kann nützlich sein, wenn Sie beispielsweise mit einer bestimmten Version vergleichen möchten.
Christian.D
89

Sie können mit dem Befehl auch eine commit hash(häufig auch aufgerufene commit ID) angeben .git show


In einer Nussschale

git show <commitHash>:/path/to/file


Schritt für Schritt

  1. Zeigen Sie das Protokoll aller Änderungen für eine bestimmte Datei mit an git log /path/to/file
  2. In der Liste der angezeigten Änderungen werden commit hashsolche wie commit 06c98...(06c98 ... als Commit-Hash) angezeigt.
  3. Kopiere das commit hash
  4. Führen Sie den Befehl git show <commitHash>:/path/to/filemit commit hashSchritt 3 und path/to/fileSchritt 1 aus.

Hinweis: Das Hinzufügen des ./bei Angabe eines relativen Pfads erscheinenden Pfads scheint wichtig zu sein, d git show b2f8be577166577c59b55e11cfff1404baf63a84:./flight-simulation/src/main/components/nav-horiz.html. H.

Adrien Be
quelle
1
Falls Sie den Pfad zur Datei nicht kennen, verwenden Sie git show <SHA1> --name-only, um ihn abzurufen.
Tiina
Dieser Befehl op - sogar automatisch aus dem Speicher vervollständigt - in einem gelöschten Verzeichnis getestet ... kann nicht mehr op als das gg
treyBake
43

Zusätzlich zu Jim Hunzikers Antwort

Sie können die Datei aus der Revision exportieren als:

git show HEAD@{2013-02-25}:./fileInCurrentDirectory.txt > old_fileInCurrentDirectory.txt

Hoffe das hilft :)

Ijas Ameenudeen
quelle
23

So erkennen Sie schnell die Unterschiede zu älteren Revisionen einer Datei:

git show -1 filename.txt > zum Vergleich mit der letzten Revision der Datei

git show -2 filename.txt > zum Vergleich mit der vorletzten Revision

git show -3 fielname.txt > zum Vergleich mit der letzten vorletzten Revision

sachin_ur
quelle
18
Diese Befehle zeigen für mich die Unterschiede zur aktuellen Version, aber nicht die gesamte Datei.
Jean Paul
18

git log -pzeigt Ihnen nicht nur die Festschreibungsprotokolle, sondern auch die Unterschiede der einzelnen Festschreibungen (mit Ausnahme der Festschreibungs-Festschreibungen). Dann können Sie drücken /, Dateinamen eingeben und drücken enter. Drücken Sie noder p, um zum nächsten / vorherigen Ereignis zu gelangen. Auf diese Weise sehen Sie nicht nur die Änderungen in der Datei, sondern auch die Festschreibungsinformationen.

Sanbor
quelle
3
Sieht so aus, als git log -pmwürde auch Merge-Commits angezeigt.
Sanbor
2
Sie können auch ausführen git log -p -- filename.txt, um den Verlauf nur auf die gewünschte Datei zu beschränken.
Jean Paul
3

Mit einem solchen Skript können Sie alle Versionen einer Datei in separate Dateien sichern:

z.B

git_dump_all_versions_of_a_file.sh path/to/somefile.txt

Holen Sie sich das Skript hier als Antwort auf eine andere ähnliche Frage

Brad Parks
quelle
1
git_root, git_log_shortUnd git_log_message_for_commitfehlen.
Mogsie
Guter Fang! Ich habe diese Antwort doppelt an zwei verschiedenen Stellen gepostet und diese einfach entfernt und mit der anderen verknüpft, wo mir die Leute vorher davon erzählt haben ... danke @mogsie!
Brad Parks
Dieses Skript ist sehr nützlich!
XMAN
3

WEG 1: (Ich bevorzuge diesen Weg)

  1. Finden Sie die Commit-ID mit:git reflog
  2. Listen Sie die Dateien aus dem Commit auf git diff-tree --no-commit-id --name-only -r <commitHash>

Beispiel: git diff-tree --no-commit-id --name-only -r d2f9ba4// "d2f9ba4" ist eine Festschreibungs-ID von "1".

  1. Öffnen Sie die benötigte Datei mit dem folgenden Befehl:

git show <commitHash>:/path/to/file

Beispiel: git show d2f9ba4:Src/Ext/MoreSwiftUI/ListCustom.swift// "Src / ..." ist der Dateipfad von "2".

WEG 2:

  1. Finden Sie die Commit-ID mit:git reflog
  2. Machen Sie einen Hard-Reset auf dieses Commit: git reset --hard %commit ID%

git reset --hard c14809fa

  1. Nehmen Sie unnötige Änderungen vor und legen Sie ein neues Commit für den benötigten Zweig fest :)
Andrew
quelle
0

Hilfsprogramm zum Abrufen mehrerer Dateien aus einer bestimmten Revision

Wenn Sie versuchen, Zusammenführungskonflikte zu lösen, ist dieser Helfer sehr nützlich:

#!/usr/bin/env python3

import argparse
import os
import subprocess

parser = argparse.ArgumentParser()
parser.add_argument('revision')
parser.add_argument('files', nargs='+')
args = parser.parse_args()
toplevel = subprocess.check_output(['git', 'rev-parse', '--show-toplevel']).rstrip().decode()
for path in args.files:
    file_relative = os.path.relpath(os.path.abspath(path), toplevel)
    base, ext = os.path.splitext(path)
    new_path = base + '.old' + ext
    with open(new_path, 'w') as f:
        subprocess.call(['git', 'show', '{}:./{}'.format(args.revision, path)], stdout=f)

GitHub stromaufwärts .

Verwendungszweck:

git-show-save other-branch file1.c path/to/file2.cpp

Ergebnis: Die folgenden Versionen enthalten die alternativen Versionen der Dateien:

file1.old.c
path/to/file2.old.cpp

Auf diese Weise behalten Sie die Dateierweiterung bei, damit sich Ihr Editor nicht beschwert und die alte Datei direkt neben der neueren Datei leicht findet.

Ciro Santilli 冠状 病毒 审查 六四 事件 法轮功
quelle
@MickeyPerlstein Wenn Sie die gleiche Schnittstelle mit einer besseren Implementierung erreichen können, bin ich ganz Ohr.
Ciro Santilli 法轮功 病毒 审查 六四 事件 24
Vielleicht verstehe ich es nicht (und wenn ja, ich entschuldige mich), aber ist es nicht nur: "git show version: ./ path> new_path"?
Mickey Perlstein
@MickeyPerlstein Hallo, ja, mein Befehl generiert diese CLI, aber er durchläuft mehrere Dateien und erzeugt einen Ausgabenamen aus der Eingabe, sodass Sie nicht zu viel eingeben müssen. Natürlich nichts Revolutionäres, aber praktisch.
Ciro Santilli 法轮功 病毒 审查 六四 事件 26