Как получить один файл из определенной ревизии в Git - PullRequest
745 голосов
/ 04 марта 2009

У меня есть Git-репозиторий, и я хотел бы посмотреть, как какой-то файл выглядел несколько месяцев назад. Я нашел ревизию в тот день, и она 27cf8e84bb88e24ae4b4b3df2b77aab91a3735d8. Мне нужно посмотреть, как выглядел один файл, и сохранить его в файл.

Мне удалось увидеть файл, используя gitk, но у него нет возможности сохранить его. Я попытался с инструментами командной строки, самое близкое, которое я получил, было:

git-show 27cf8e84bb88e24ae4b4b3df2b77aab91a3735d8 my_file.txt

Однако, эта команда показывает diff, а не содержимое файла. Я знаю, что позже смогу использовать что-то вроде PAGER=cat и перенаправить вывод в файл, но не знаю, как добраться до реального содержимого файла.

По сути, я ищу что-то вроде svn cat .

Ответы [ 8 ]

656 голосов
/ 04 марта 2009

Чтобы завершить свой собственный ответ, синтаксис действительно

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

Команда принимает обычный стиль ревизии, что означает, что вы можете использовать любое из следующего:

  1. название филиала (как предлагается от ash )
  2. HEAD + x количество ^ символов
  3. Хэш SHA1 данной ревизии
  4. Первые несколько (может быть, 5) символов данного хэша SHA1

Совет Важно помнить, что при использовании "git show", всегда указывает путь от корня хранилища , а не от текущей позиции каталога.

(Хотя Mike Morearty упоминает, что, по крайней мере с git 1.7.5.4, вы можете указать относительный путь, поставив "./" в начале пути - например:

git show HEAD^^:./test.py

)


До git1.5.x это было сделано с помощью некоторой сантехники:

git ls-tree <rev>
показать список одного или нескольких объектов blob в коммите

git cat-file blob <file-SHA1>
cat файл, поскольку он был зафиксирован в определенной ревизии (аналогично svn кошка). используйте git ls-tree для получения значения заданного файла-sha1

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

git-ls-tree перечисляет идентификатор объекта для $ file в ревизии $ REV, это вырезано из выходных данных и используется в качестве аргумента для git-cat-file, который действительно должен называться git-cat-object, и просто сбрасывает этот объект в стандартный вывод.


Примечание: начиная с Git 2.11 (4 квартал 2016 г.), вы можете применить фильтр содержимого к выводу git cat-file!

См. commit 3214594 , commit 7bcf341 (09 сентября 2016 г.), commit 7bcf341 (09 сентября 2016 г.) и commit b9e62f6, коммит 16dcc29 (24 августа 2016 г.) Йоханнес Шинделин (dscho) .
(Объединено с Junio ​​C Hamano - gitster - в коммит 7889ed2 , 21 сентября 2016 г.)

cat-file: поддержка --textconv / --filters в пакетном режиме

Несмотря на то, что «git hash-objects», который является инструментом для получения потока данных внутри файловой системы и помещения его в хранилище объектов Git, позволял выполнять «внешний мир для Git» «преобразования (например, преобразования в конец строки и применение чистого фильтра), и с самого начала у него была функция по умолчанию, обратная операция« git cat-file », которая требует объект из хранилища объектов Git и внешний для потребления внешним миром, отсутствовал эквивалентный механизм для запуска «Git-to-outside-world»

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

Примечание: "git cat-file --textconv" недавно начал segfaulting (2017), который исправлено в Git 2.15 (4 квартал 2017 г.)

См. commit cc0ea7c (21 сентября 2017) Джефф Кинг (peff) .
(Объединено с Junio ​​C Hamano - gitster - в commit bfbc2fc , 28 сентября 2017 г.)

468 голосов
/ 18 ноября 2010

Если вы хотите заменить / перезаписать содержимое файла в текущей ветке содержимым файла из предыдущего коммита или другой ветви, вы можете сделать это с помощью следующих команд:

git checkout 08618129e66127921fbfcbc205a06153c92622fe path/to/file.txt

или

git checkout mybranchname path/to/file.txt

Затем вам нужно будет зафиксировать эти изменения, чтобы они вступили в силу в текущей ветви.

138 голосов
/ 04 марта 2009

Вам необходимо указать полный путь к файлу:

git show 27cf8e84bb88e24ae4b4b3df2b77aab91a3735d8:full/repo/path/to/my_file.txt
80 голосов
/ 07 июля 2015

Самый простой способ - написать:

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

где:

  • HASH - это хэш-номер редакции Git SHA-1
  • file / path / name.ext - это имя файла, который вы ищете
  • some_new_name.ext - путь и имя, в котором должен быть сохранен старый файл
* * Пример тысяча двадцать-одина * * тысяча двадцать-дв
git show 27cf8e84bb88e24ae4b4b3df2b77aab91a3735d8:my_file.txt > my_file.txt.OLD

Это сохранит my_file.txt от версии 27cf8e как новый файл с именем my_file.txt.OLD

Было протестировано с Git 2.4.5.

Если вы хотите восстановить удаленный файл, вы можете использовать HASH~1 (один коммит до указанного HASH).

* +1039 * Пример:
git show 27cf8e84bb88e24ae4b4b3df2b77aab91a3735d8~1:deleted_file.txt > deleted_file.txt
10 голосов
/ 02 марта 2015

В Windows с Git Bash:

  • в вашем рабочем пространстве, измените dir на папку, в которой находится ваш файл
  • git show cab485c83b53d56846eb883babaaf4dff2f2cc46:./your_file.ext > old.ext
6 голосов
/ 01 января 2014

И, чтобы красиво сбросить его в файл (по крайней мере, на Windows) - Git Bash:

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

Кавычки " необходимы, чтобы сохранить переводы строк.

3 голосов
/ 24 июля 2014

Это поможет вам получить все удаленные файлы между коммитами без указания пути, полезно, если удалено много файлов.

git diff --name-only --diff-filter=D $commit~1 $commit | xargs git checkout $commit~1
0 голосов
/ 22 июля 2011

Получить файл из предыдущего коммита путем извлечения предыдущего коммита и копирования файла.

  • Обратите внимание, на какой ветке вы находитесь: git branch
  • Оформить предыдущий коммит вы хотите: git checkout 27cf8e84bb88e24ae4b4b3df2b77aab91a3735d8
  • Скопируйте файл, который вы хотите, во временную папку
  • Оформить ветку, с которой вы начали: git checkout theBranchYouNoted
  • Скопируйте файл, который вы поместили во временную папку
  • Передайте изменения в git: git commit -m "added file ?? from previous commit"
...