Есть ли быстрая команда Git, чтобы увидеть старую версию файла?


1511

Есть ли в Git команда для просмотра (либо выгрузки в stdout, либо в $PAGERили $EDITOR) конкретной версии определенного файла?



Если вы пришли к этому вопросу, потому что хотите проверить более старую версию бинарного файла (например, изображение), то лучше выполнить проверку для старого коммита, посмотреть, что вам нужно увидеть, а затем вернуться к HEAD. Для этого сделайте git checkout <sha1-of-the-commit-you-need>потомgit checkout HEAD
Homero Esmeraldo

Ответы:


1732

Вы можете использовать git showс путем от корня хранилища ( ./или ../для относительного пути):

$ git show REVISION:path/to/file

Замените его REVISIONфактической ревизией (это может быть SHA коммита Git, имя тега, имя ветки, относительное имя коммита или любой другой способ идентификации коммита в Git)

Например, чтобы просмотреть версию файла <repository-root>/src/main.cот 4 коммитов назад, используйте:

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

Git для Windows требует прямой косой черты даже в путях относительно текущего каталога. Для получения дополнительной информации посетите страницу справочника git-show.


5
Это на самом деле не работает - вы пробовали это? Для "git show HEAD: path / to / file.c" я получаю ошибку "неоднозначный аргумент".
Майк

2
Должен быть полный путь от вершины git repo
richq

20
Если вы работаете в Windows, это может быть разделитель пути; если я делаю git show HEAD: dir \ subdir \ file, я получаю двусмысленный аргумент. Если я делаю git show HEAD: dir / subdir / file, он работает как положено.
Мэтт МакМинн

12
Путь, который вы должны указать после: находится в корне репозитория git. (это было дано ниже как ответ, но я думаю, что это было предназначено как комментарий к этому ответу)
MatrixFrog

9
Если вы хотите увидеть это в разделении Vim, чтобы они прокручивались вместе, я написал короткое сообщение в блоге, показывающее, как это сделать.
Флавиу

257

Делать это по дате выглядит так:

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

Обратите внимание, что HEAD@{2013-02-25}в этом хранилище (где использовался reflog ) означает «где HEAD был 2013-02-25» , а не «последний коммит до 2013-02-25 в этой ветви в истории».


5
Потрясающие. Экономит мое время, вместо того, чтобы ходить на github и смотреть на коммит.
Fizer Khan

«Точка» на пути к файлу была моей проблемой. Спасибо!
Томашарад

5
Эта команда полезна с masterвместо HEAD@{2013-02-25}, если вы находитесь на ветке
funroll

1
Можете ли вы включить время, а-ля git log --since='2016-04-28 23:59:59 +0100'?
Дамблдэд

7
Тот факт, что этот синтаксис использует reflog, важен и должен быть особо выделен, потому что reflog не содержит все коммиты . См. Blog.endpoint.com/2014/05/git-checkout-at-specific-date.html
Алиса Хитон,

113

Если вам нравятся графические интерфейсы, вы можете использовать gitk:

  1. начать гитк с:

    gitk /path/to/file
    
  2. Выберите редакцию в верхней части экрана, например, по описанию или дате. По умолчанию в нижней части экрана отображается разница для этой ревизии (в соответствии с переключателем «patch»).

  3. Чтобы просмотреть файл для выбранной ревизии:

    • Нажмите на кнопку «дерево». Это покажет корень дерева файлов в этой ревизии.
    • Разверните файл.

7
Это также работает с Tig , который является средством просмотра git repo curses.
Мэтью Дж

1
@Paul Slocum: Может быть потому, что эта команда не является обычной командой, а не встроенной в git. Я думаю, что эта команда работает только для Windows.
Envil

Обратите внимание, что это работает, только если вы начинаете с корня вашего git-репозитория.
Марк

Если вы хотите проверить против определенного пересмотра с gitk вы также можете использовать этот ярлык: gitk REVISION /path/to/file. Это может пригодиться, если вы хотите проверить, например, с определенной версией.
Christian.D

89

Вы также можете указать commit hash(часто также вызывается commit ID) с помощью git showкоманды .


В двух словах

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


Шаг за шагом

  1. Показать журнал всех изменений для данного файла с git log /path/to/file
  2. В показанном списке изменений показано, commit hashнапример, commit 06c98...(06c98 ... хеш коммита)
  3. Скопируйте commit hash
  4. Запустите команду, git show <commitHash>:/path/to/fileиспользуя commit hashшаг 3 и path/to/fileшаг 1.

Примечание: добавляя ./при указании относительного пути представляется важным, то есть git show b2f8be577166577c59b55e11cfff1404baf63a84:./flight-simulation/src/main/components/nav-horiz.html.


1
если вы не знаете путь к файлу, используйте его git show <SHA1> --name-onlyдля получения.
Тийна

эта команда op - даже автоматически завершается из памяти - протестирована в удаленном каталоге ... не может получить больше
операций,

43

В дополнение к ответу Джима Хунзикера ,

Вы можете экспортировать файл из ревизии как,

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

Надеюсь это поможет :)


23

Чтобы быстро увидеть различия со старыми ревизиями файла:

git show -1 filename.txt > сравнить с последней ревизией файла

git show -2 filename.txt > сравнить со 2-ой последней ревизией

git show -3 fielname.txt > сравнить с последней 3-ей последней ревизией


18
Эти команды показывают различия с текущей версией для меня, но не показывают весь файл.
Жан Поль

18

git log -pпокажет вам не только логи коммитов, но и различия каждого коммита (кроме коммитов слияния). Затем вы можете нажать /, введите имя файла и нажмите enter. Нажмите nили, pчтобы перейти к следующему / предыдущему вхождению. Таким образом, вы увидите не только изменения в файле, но и информацию о фиксации.


3
Похоже, git log -pmбудет также показывать слияния коммитов.
Санбор

2
Вы также можете запустить, git log -p -- filename.txtчтобы ограничить историю только желаемым файлом.
Жан Поль

3

Вы можете использовать такой скрипт, чтобы вывести все версии файла в отдельные файлы:

например

git_dump_all_versions_of_a_file.sh path/to/somefile.txt

Получите скрипт здесь как ответ на другой похожий вопрос


1
git_root, git_log_shortИ git_log_message_for_commitне хватает.
mogsie

Хороший улов! Я дважды опубликовал этот ответ в 2 разных местах, и просто удалил этот и связал его с другим, где люди рассказывали мне об этом раньше ... спасибо @mogsie!
Брэд Паркс

Этот скрипт очень полезен!
XMAN

3

ПУТЬ 1: (Я предпочитаю этот путь)

  1. Найти идентификатор коммита с помощью:git reflog
  2. Список файлов из коммита git diff-tree --no-commit-id --name-only -r <commitHash>

пример: git diff-tree --no-commit-id --name-only -r d2f9ba4// "d2f9ba4" это идентификатор коммита из "1."

  1. Откройте нужный файл командой:

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

пример: git show d2f9ba4:Src/Ext/MoreSwiftUI/ListCustom.swift// "Src / ..." это путь к файлу от "2."

ПУТЬ 2:

  1. Найти идентификатор коммита с помощью:git reflog
  2. сделать hard reset на этот коммит: git reset --hard %commit ID%

git reset --hard c14809fa

  1. внесите любые ненужные изменения и сделайте новый коммит в нужную ветку :)

0

Помощник для извлечения нескольких файлов из данной ревизии

При попытке разрешить конфликты слияния этот помощник очень полезен:

#!/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 вверх по течению .

Применение:

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

Результат: следующие содержат альтернативные версии файлов:

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

Таким образом, вы сохраняете расширение файла, чтобы ваш редактор не жаловался и мог легко найти старый файл рядом с новым.


@MickeyPerlstein, если вы можете добиться того же интерфейса с лучшей реализацией, я весь слух.
Сиро Сантилли 郝海东 冠状 病 六四 事件 法轮功

возможно я не понимаю (и если так, мои извинения), но разве это не просто: "git show version: ./ path> new_path"?
Микки

@MickeyPerlstein Привет, да, моя команда генерирует этот CLI, но он перебирает несколько файлов и выдает имя вывода из ввода, поэтому вам не нужно вводить слишком много. Ничего революционного конечно, но удобно.
Сиро Сантилли 郝海东 冠状 病 六四 事件 法轮功
Используя наш сайт, вы подтверждаете, что прочитали и поняли нашу Политику в отношении файлов cookie и Политику конфиденциальности.
Licensed under cc by-sa 3.0 with attribution required.