Czy istnieje szybkie polecenie Git, aby zobaczyć starą wersję pliku?

1509

Czy w Git jest polecenie, aby zobaczyć (zrzuconą na standardowe wyjście lub w $PAGERlub $EDITOR) określoną wersję określonego pliku?

mikrofon
źródło
Jeśli przyszedłeś do tego pytania, ponieważ chcesz sprawdzić starszą wersję pliku binarnego (np. Obraz), to lepiej wykonaj kasę do starego zatwierdzenia, zobacz, co musisz zobaczyć, a następnie wróć do HEAD. W tym celu wykonaj git checkout <sha1-of-the-commit-you-need>późniejgit checkout HEAD
Homero Esmeraldo

Odpowiedzi:

1730

Możesz użyć git showścieżki z katalogu głównego repozytorium ( ./lub ../względnej ścieżki ):

$ git show REVISION:path/to/file

Zastąp REVISIONaktualną wersją (może to być SHA zatwierdzenia Git, nazwa znacznika, nazwa gałęzi, względna nazwa zatwierdzenia lub inny sposób identyfikacji zatwierdzenia w Git)

Na przykład, aby wyświetlić wersję pliku <repository-root>/src/main.csprzed 4 zatwierdzeń, użyj:

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

Git dla Windows wymaga ukośników nawet w ścieżkach względem bieżącego katalogu. Aby uzyskać więcej informacji, sprawdź stronę podręcznika dla git-show.

mipadi
źródło
5
To tak naprawdę nie działa - próbowałeś? W przypadku „git show HEAD: path / to / file.c” pojawia się błąd „dwuznaczny argument”.
Mike
2
Musi to być pełna ścieżka od szczytu repozytorium git
richq
20
Jeśli korzystasz z systemu Windows, może to być separator ścieżki; jeśli zrobię git show HEAD: dir \ subdir \ file, otrzymam jednoznaczny argument. Jeśli zrobię git show HEAD: dir / subdir / file, działa zgodnie z oczekiwaniami.
Matt McMinn
12
Ścieżka, którą musisz podać po: jest z katalogu głównego repozytorium git. (podano to poniżej jako odpowiedź, ale myślę, że miało to być komentarzem do tej odpowiedzi)
MatrixFrog
9
Jeśli chcesz zobaczyć to w Vimie, aby przewijały się razem, napisałem krótki post na blogu pokazujący, jak to zrobić.
Flaviu,
257

Wykonanie tego według daty wygląda następująco:

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

Zauważ, że HEAD@{2013-02-25}oznacza to „gdzie HEAD był w dniu 25.02.2013” ​​w tym repozytorium (używając reflog ), a nie „ostatni zatwierdzenie przed 25.02.2013 w tej gałęzi w historii”.

Jim Hunziker
źródło
5
Niesamowite. Oszczędza dużo czasu zamiast chodzić na github i patrzeć na zatwierdzenie.
Fizer Khan,
„Kropka” na ścieżce pliku była moim problemem. Dzięki!
tomascharad
5
To polecenie jest przydatne masterzamiast HEAD@{2013-02-25}, jeśli jesteś na gałęzi
funroll
1
Czy możesz podać czas, la git log --since='2016-04-28 23:59:59 +0100'?
dumbledad
7
Fakt, że ta składnia używa reflogu, jest ważny i powinien być mocno podkreślony, ponieważ reflog nie zawiera wszystkich zatwierdzeń . Zobacz blog.endpoint.com/2014/05/git-checkout-at-specific-date.html
Alice Heaton
113

Jeśli lubisz GUI, możesz użyć gitk:

  1. uruchom gitk za pomocą:

    gitk /path/to/file
    
  2. Wybierz wersję w górnej części ekranu, np. Według opisu lub daty. Domyślnie dolna część ekranu pokazuje różnicę dla tej wersji (odpowiadająca przyciskowi opcji „łatka”).

  3. Aby zobaczyć plik dla wybranej wersji:

    • Kliknij przycisk radiowy „drzewo”. Spowoduje to wyświetlenie katalogu głównego drzewa plików w tej wersji.
    • Przejdź do swojego pliku.
Trausti Kristjansson
źródło
7
Działa to również z tig , który jest przeglądarką git repo przekleństw.
Matthew G
1
@Paul Slocum: Może być, ponieważ to polecenie nie jest konwencjonalnym poleceniem, a nie wbudowanym programem git. Myślę, że to polecenie działa tylko w systemie Windows.
Wysłannik
Zauważ, że działa to tylko wtedy, gdy zaczynasz od katalogu głównego repozytorium git.
Marc
Jeśli chcesz sprawdzić przed pewnej rewizji z gitk można też użyć tego skrótu: gitk REVISION /path/to/file. Może się to przydać, gdy chcesz na przykład sprawdzić pewną wersję.
Christian.D.
89

Możesz także określić commit hash(często nazywany commit ID) git showpoleceniem .


W skrócie

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


Krok po kroku

  1. Pokaż dziennik wszystkich zmian dla danego pliku za pomocą git log /path/to/file
  2. Na pokazanej liście zmian pokazuje commit hashtakie, jak commit 06c98...(06c98 ... będący skrótem zatwierdzenia)
  3. Skopiuj commit hash
  4. Uruchom polecenie, git show <commitHash>:/path/to/fileużywając commit hashkroku 3 i path/to/filekroku 1.

Uwaga: dodanie ./przy określaniu ścieżki względnej wydaje się ważne, tj git show b2f8be577166577c59b55e11cfff1404baf63a84:./flight-simulation/src/main/components/nav-horiz.html.

Adrien Be
źródło
1
jeśli nie znasz ścieżki do pliku, użyj jej, git show <SHA1> --name-onlyaby ją zdobyć.
Tiina,
to polecenie op - nawet auto uzupełnia z pamięci - testowane w usuniętym katalogu ... nie można uzyskać więcej
operacji
43

Oprócz Jim Hunziker „s odpowiedź

możesz wyeksportować plik z wersji jako,

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

Mam nadzieję że to pomoże :)

Ijas Ameenudeen
źródło
23

Aby szybko zobaczyć różnice w starszych wersjach pliku:

git show -1 filename.txt > aby porównać z ostatnią wersją pliku

git show -2 filename.txt > aby porównać z 2. ostatnią wersją

git show -3 fielname.txt > aby porównać z ostatnią trzecią ostatnią wersją

sachin_ur
źródło
18
Te polecenia pokazują dla mnie różnice w obecnej wersji, ale nie pokazują całego pliku.
Jean Paul
18

git log -ppokaże ci nie tylko dzienniki zatwierdzeń, ale także różnicę każdego zatwierdzenia (z wyjątkiem zatwierdzeń scalania). Następnie możesz nacisnąć /, wprowadzić nazwę pliku i nacisnąć enter. Naciśnij nlub, paby przejść do następnego / poprzedniego wystąpienia. W ten sposób zobaczysz nie tylko zmiany w pliku, ale także informacje o zatwierdzeniu.

sanbor
źródło
3
Wygląda na to, git log -pmże pokazywałby również zatwierdzenia scalania.
sanbor
2
Możesz także uruchomić, git log -p -- filename.txtaby ograniczyć historię tylko do żądanego pliku.
Jean Paul
3

Możesz użyć takiego skryptu, aby zrzucić wszystkie wersje pliku w celu oddzielenia plików:

na przykład

git_dump_all_versions_of_a_file.sh path/to/somefile.txt

Pobierz skrypt tutaj jako odpowiedź na kolejne podobne pytanie

Brad Parks
źródło
1
git_root, git_log_shortA git_log_message_for_commitbrakuje.
mogsie
Dobry chwyt! Dwukrotnie opublikowałem tę odpowiedź w 2 różnych miejscach, po prostu usunąłem tę i powiązałem z drugą, gdzie ludzie mówili mi o tym wcześniej ... dzięki @mogsie!
Brad Parks
Ten skrypt jest bardzo przydatny!
XMAN,
3

SPOSÓB 1: (Wolę w ten sposób)

  1. Znajdź identyfikator zatwierdzenia za pomocą:git reflog
  2. Lista plików z zatwierdzenia git diff-tree --no-commit-id --name-only -r <commitHash>

przykład: git diff-tree --no-commit-id --name-only -r d2f9ba4// „d2f9ba4” to identyfikator zatwierdzenia z „1.”

  1. Otwórz potrzebny plik za pomocą polecenia:

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

przykład: git show d2f9ba4:Src/Ext/MoreSwiftUI/ListCustom.swift// „Src / ...” to ścieżka do pliku z „2”

SPOSÓB 2:

  1. Znajdź identyfikator zatwierdzenia za pomocą:git reflog
  2. wykonaj twardy reset tego zatwierdzenia: git reset --hard %commit ID%

git reset --hard c14809fa

  1. wprowadź niepotrzebne zmiany i dokonaj nowego zatwierdzenia w potrzebnej gałęzi :)
Andrzej
źródło
0

Pomocnik, aby pobrać wiele plików z danej wersji

Podczas próby rozwiązania konfliktów scalania ten pomocnik jest bardzo przydatny:

#!/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 w górę .

Stosowanie:

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

Wynik: poniższe zawierają alternatywne wersje plików:

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

W ten sposób zachowujesz rozszerzenie pliku, aby Twój edytor nie narzekał i mógł łatwo znaleźć stary plik tuż obok nowszego.

Ciro Santilli
źródło
@MickeyPerlstein, jeśli potrafisz osiągnąć ten sam interfejs dzięki lepszej implementacji, jestem cała w uszach.
Ciro Santilli 冠状 病毒 审查 六四 事件 法轮功
może nie rozumiem (a jeśli tak, przepraszam), ale czy nie jest to po prostu: „git show version: ./ path> new_path”?
Mickey Perlstein
@MickeyPerlstein cześć, tak, moje polecenie generuje interfejs CLI, ale zapętla wiele plików i generuje nazwę wyjściową na podstawie danych wejściowych, więc nie musisz pisać zbyt wiele. Oczywiście nic rewolucyjnego, ale wygodne.
Ciro Santilli 26 病毒 审查 六四 事件 法轮功