Как получить один файл из определенной ревизии в Git

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

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

git-show 27cf8e84bb88e24ae4b4b3df2b77aab91a3735d8 my_file.txt

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

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

Ответ 1

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

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).
(Merged by Junio C Hamano -- [TG411] -- in commit 7889ed2, 21 Sep 2016)

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

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

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

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

См. commit cc0ea7c (21 сентября 2017 г.) автора Джеффа Кинга (peff).
(Merged by Junio C Hamano -- [TG420] -- in commit bfbc2fc, 28 Sep 2017)


Обратите внимание, что для переопределения/замены файла с прошлым содержимым вам больше не следует использовать сбивающую с толку команду git checkout, а git restore (Git 2 23+, август 2019 г.)

git restore -s <SHA1> -- afile

Это восстановит в рабочем дереве только тот файл, который присутствует в коммите "source" (-s) SHA1.
Чтобы восстановить также индекс:

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

(-SW: сокращение от --staged --worktree)

Ответ 2

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

git checkout 08618129e66127921fbfcbc205a06153c92622fe path/to/file.txt

или

git checkout mybranchname path/to/file.txt

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

Ответ 3

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

git show 27cf8e84bb88e24ae4b4b3df2b77aab91a3735d8:full/repo/path/to/my_file.txt

Ответ 4

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

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).

Пример:

git show 27cf8e84bb88e24ae4b4b3df2b77aab91a3735d8~1:deleted_file.txt > deleted_file.txt

Ответ 5

В Windows с Git Bash:

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

Ответ 6

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

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

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

Ответ 7

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

git diff --name-only --diff-filter=D $commit~1 $commit | xargs git checkout $commit~1

Ответ 8

git checkout {SHA1} -- filename

эта команда получает скопированный файл с определенного коммита.

Ответ 9

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

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