Jak odzyskać pojedynczy plik z określonej rewizji w Git?
Mam repozytorium Git i chciałbym zobaczyć jak niektóre pliki wyglądały kilka miesięcy temu. Znalazłem rewizję w tym dniu; jest 27cf8e84bb88e24ae4b4b3df2b77aab91a3735d8
. Muszę zobaczyć, jak wygląda jeden plik, a także zapisać go jako ("nowy") plik.
Udało mi się zobaczyć plik używając gitk
, ale nie ma opcji, aby go zapisać. Próbowałem z narzędziami wiersza poleceń, najbliżej było:
git-show 27cf8e84bb88e24ae4b4b3df2b77aab91a3735d8 my_file.txt
Jednak to polecenie pokazuje różnicę, a nie Zawartość pliku. Wiem, że mogę później użyć czegoś takiego jak PAGER=cat
i przekierowanie wyjścia do pliku, ale nie wiem, jak dostać się do rzeczywistej zawartości pliku.
Zasadniczo szukam czegoś w rodzaju svn cat.
11 answers
Za pomocą git show
Aby uzupełnić własną odpowiedź, składnia jest rzeczywiście
git show object
git show $REV:$FILE
git show somebranch:from/the/root/myfile.txt
git show HEAD^^^:test/test.py
Polecenie przyjmuje zwykły styl rewizji, co oznacza, że możesz użyć dowolnego z następujących poleceń:
- branch name (as suggested by ash)
-
HEAD
+ x liczba^
znaków - hash SHA1 danej wersji
- kilka pierwszych (Może 5) znaków danego hasha SHA1
Wskazówka ważne jest, aby pamiętać, że podczas używania "git show
", zawsze należy podać ścieżkę z katalogu głównego repozytorium, a nie bieżącą pozycję katalogu.
(chociaż Mike Morearty wspomina, że przynajmniej w git 1.7.5.4, możesz określić ścieżkę względną, umieszczając "./
" na początku ścieżki. Na przykład:
git show HEAD^^:./test.py
)
Za pomocą git restore
Z Git 2.23+ (Sierpień 2019), możesz również użyć git restore
który zastępuje mylące git checkout
polecenie
git restore -s <SHA1> -- afile
git restore -s somebranch -- afile
, który przywróci na drzewie roboczym tylko plik obecny w źródle "" (-s
) commit SHA1 lub branch somebranch
.
Aby przywrócić również indeks:
git restore -s <SHA1> -SW -- afile
(-SW
: skrót od --staged --worktree
)
Używanie niskopoziomowych poleceń git plumbing
Przed git1. 5.x, to było zrobione jakimś kanalizacją:
git ls-tree <rev>
pokazuje listę co najmniej jednego obiektu 'blob' w commicie
git cat-file blob <file-SHA1>
cat a file as it has been committed w ramach określonej rewizji (podobnej do svn
cat).
użyj git ls-tree
, aby pobrać wartość podanego pliku-sha1
git cat-file -p $(git-ls-tree $REV $file | cut -d " " -f 3 | cut -f 1)::
git-ls-tree
wyświetla ID obiektu $file
w revision $REV
, jest on wycięty z wyjścia i używany jako argument do git-cat-file
, który powinien być naprawdę nazywany git-cat-object
, i po prostu zrzuca ten obiekt do stdout
.
Uwaga: Od wersji Git 2.11 (Q4 2016), możesz zastosować filtr zawartości do wyjścia git cat-file
.
Zobacz
commit 3214594 ,
commit 7bcf341 (09 wrz 2016),
commit 7bcf341 (09 wrz 2016), oraz
commit b9e62f6 ,
commit 16dcc29 (24 sierpnia 2016) by Johannes Schindelin (dscho
).
(dodane przez Junio C Hamano -- gitster
-- in commit 7889ed2, 21 Sep 2016)
git config diff.txt.textconv "tr A-Za-z N-ZA-Mn-za-m <"
git cat-file --textconv --batch
W 2017 roku segfaulting został poprawiony w Git 2.15 (Q4 2017) {[36]]}
Zobacz commit cc0ea7c (21 września 2017) by Jeff King (peff
).
(dodane przez Junio C Hamano -- gitster
-- in commit bfbc2fc, 28 Sep 2017)
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2020-07-25 19:23:07
Jeśli chcesz zastąpić / zastąpić Zawartość pliku w bieżącej gałęzi zawartością pliku z poprzedniego commita lub innej gałęzi, możesz to zrobić za pomocą następujących poleceń:
git checkout 08618129e66127921fbfcbc205a06153c92622fe path/to/file.txt
Lub
git checkout mybranchname path/to/file.txt
Będziesz musiał zatwierdzić te zmiany, aby były skuteczne w bieżącej gałęzi.
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2016-12-01 16:12:41
Musisz podać pełną ścieżkę do pliku:
git show 27cf8e84bb88e24ae4b4b3df2b77aab91a3735d8:full/repo/path/to/my_file.txt
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2018-07-20 23:52:09
Najprostszym sposobem jest napisanie:
git show HASH:file/path/name.ext > some_new_name.ext
Gdzie:
- HASH jest numerem skrótu Git revision SHA-1
- plik / ścieżka / nazwa.ext to nazwa pliku, którego szukasz
- some_new_name.ext jest ścieżką i nazwą, do której należy zapisać stary plik
Przykład
git show 27cf8e84bb88e24ae4b4b3df2b77aab91a3735d8:my_file.txt > my_file.txt.OLD
To zapisze my_file.txt z rewizji 27cf8ejako nowy plik o nazwie my_file.txt.OLD
To było testowane z Git 2.4.5.
Jeśli chcesz odzyskać usunięty plik możesz użyć HASH~1
(jeden commit przed podanym Hashem).
Przykład:
git show 27cf8e84bb88e24ae4b4b3df2b77aab91a3735d8~1:deleted_file.txt > deleted_file.txt
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2020-06-20 09:12:55
W Windows, z Git Bash:
- w obszarze roboczym zmień katalog do folderu, w którym mieszka Twój plik
git show cab485c83b53d56846eb883babaaf4dff2f2cc46:./your_file.ext > old.ext
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2015-03-02 16:17:24
I ładnie wrzucić go do pliku (przynajmniej na Windows) - Git Bash:
$ echo "`git show 60d8bdfc:src/services/LocationMonitor.java`" >> LM_60d8bdfc.java
Cudzysłowy "
są potrzebne, aby zachować nowe linie.
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2018-07-20 23:53:50
git checkout {SHA1} -- filename
To polecenie pobiera skopiowany plik z określonego commita.
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2019-09-28 19:42:48
To pomoże ci uzyskać wszystkie usunięte pliki między zatwierdzeniami bez podawania ścieżki, przydatne, jeśli istnieje wiele usuniętych plików.
git diff --name-only --diff-filter=D $commit~1 $commit | xargs git checkout $commit~1
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2014-07-24 02:34:05
Oprócz wszystkich opcji wymienionych w innych odpowiedziach, możesz użyć git reset
z obiektem Git (hash, branch, HEAD~x
, tag,...) interesującego i ścieżki pliku:
git reset <hash> /path/to/file
W twoim przykładzie:
git reset 27cf8e8 my_file.txt
To powoduje, że powróci my_file.txt
do swojej wersji w zatwierdzeniu 27cf8e8
w indeksie, pozostawiając ją nietkniętą (tak jak w bieżącej wersji) w katalogu roboczym.
Stamtąd wszystko jest bardzo proste:
- możesz porównać dwie wersje Twojego pliku z
git diff --cached my_file.txt
- możesz pozbyć się starej wersji pliku za pomocą
git restore --staged file.txt
(lub, przed Git v2.23,git reset file.txt
) jeśli zdecydujesz, że ci się nie podoba - możesz przywrócić starą wersję za pomocą
git commit -m "Restore version of file.txt from 27cf8e8"
igit restore file.txt
(lub, przed Git v2.23,git checkout -- file.txt
) - możesz dodawać aktualizacje ze starej do nowej wersji tylko dla niektórych kawałków, uruchamiając
git add -p file.txt
(następniegit commit
igit restore file.txt
).
Wreszcie, można nawet interaktywnie wybrać i wybrać, które hunk (s) do resetowania w bardzo pierwszy krok po uruchomieniu:
git reset -p 27cf8e8 my_file.txt
Tak więc git reset
ze ścieżką daje dużą elastyczność pobierania określonej wersji pliku w celu porównania z aktualnie pobraną wersją i, jeśli zdecydujesz się to zrobić, aby przywrócić w pełni lub tylko dla niektórych fragmentów do tej wersji.
Edit: właśnie zdałem sobie sprawę, że nie odpowiadam na twoje pytanie, ponieważ to, co chciałeś, nie było diffem ani łatwym sposobem na odzyskanie części lub całości starej wersji, ale po prostu cat
, że wersja.
Oczywiście nadal możesz to zrobić po zresetowaniu pliku za pomocą:
git show :file.txt
Do wyjścia na standardowe wyjście lub
git show :file.txt > file_at_27cf8e8.txt
Ale jeśli to było wszystko, czego chciałeś, bieganie git show
bezpośrednio z git show 27cf8e8:file.txt
, jak sugerowali inni, jest oczywiście o wiele bardziej bezpośrednie.
Zostawię jednak tę odpowiedź, ponieważ uruchamianie git show
bezpośrednio pozwala na natychmiastowe uzyskanie starej wersji, ale jeśli chcesz coś z nią zrobić, nie jest to aż tak wygodne, aby to zrobić jest, jeśli zresetujesz tę wersję w indeksie.
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2020-09-14 00:21:26
Użycie git show $REV:$FILE
, Jak już wskazywali inni, jest prawdopodobnie właściwą odpowiedzią. Zamieszczam kolejną odpowiedź, ponieważ kiedy próbowałem tej metody, czasami dostałem następujący błąd od git:
fatal: path 'link/foo' exists on disk, but not in 'HEAD'
Problem występuje, gdy część ścieżki do pliku jest dowiązaniem symbolicznym. W takich przypadkach metoda git show $REV:$FILE
będzie działać , a nie. Kroki do odtworzenia:
$ git init .
$ mkdir test
$ echo hello > test/foo
$ ln -s test link
$ git add .
$ git commit -m "initial commit"
$ cat link/foo
hello
$ git show HEAD:link/foo
fatal: path 'link/foo' exists on disk, but not in 'HEAD'
Problem polega na tym, że narzędzia takie jak realpath
tutaj nie pomagają, ponieważ dowiązanie symboliczne może nie istnieć w bieżącym / align = "left" / Nie znam dobrego ogólnego rozwiązania. W moim przypadku wiedziałem, że dowiązanie symboliczne może istnieć tylko w pierwszym komponencie ścieżki, więc rozwiązałem problem używając metody git show $REV:$FILE
dwa razy. To działa, ponieważ gdy git show $REV:$FILE
jest używane na dowiązaniu symbolicznym, to jego cel jest drukowany:
$ git show HEAD:link
test
Podczas gdy w przypadku katalogów, polecenie wyświetli nagłówek, a następnie zawartość katalogu:
$ git show HEAD:test
tree HEAD:test
foo
Więc w moim przypadku właśnie sprawdziłem wyjście pierwszego wywołania git show $REV:$FILE
i jeśli była to tylko pojedyncza linia, następnie zastąpiłem pierwszy komponent mojej ścieżki wynikiem, aby rozwiązać dowiązanie symboliczne poprzez git.
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2020-12-23 11:42:54
Pobranie pliku z poprzedniego zatwierdzenia poprzez sprawdzenie poprzedniego zatwierdzenia i skopiowanie pliku.
- zwróć uwagę, na której gałęzi jesteś: Git branch
- Sprawdź poprzedni commit, który chcesz:
git checkout 27cf8e84bb88e24ae4b4b3df2b77aab91a3735d8
- skopiuj plik do tymczasowej lokalizacji
- Sprawdź gałąź, z której zacząłeś:
git checkout theBranchYouNoted
- skopiuj plik umieszczony w tymczasowej lokalizacji
- Zatwierdź swoją zmianę do git:
git commit -m "added file ?? from previous commit"
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2012-01-10 00:14:59