Как я могу просмотреть старую версию файла с помощью Git?

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


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


Ответы (10)


Вы можете использовать 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.

person mipadi    schedule 03.12.2008
comment
На самом деле это не работает - вы пробовали? Для git show HEAD: path / to / file.c я получаю ошибку неоднозначного аргумента. - person mike; 03.12.2008
comment
И если я просто сделаю git-show path / to / file.c, команда завершится успешно без вывода. - person mike; 03.12.2008
comment
С какой версией git? Другой способ сделать это - использовать git cat-file с указанием идентификатора blob-объекта (который вы можете найти с помощью ls-tree, но это трудный путь). - person Dustin; 04.12.2008
comment
Должен быть полный путь, начиная с репозитория git - person richq; 04.12.2008
comment
Если вы работаете в Windows, это может быть разделитель путей; если я сделаю git show HEAD: dir \ subdir \ file, я получу неоднозначный аргумент. Если я сделаю git show HEAD: dir / subdir / file, он будет работать, как ожидалось. - person Matt McMinn; 21.07.2010
comment
Путь, который вы должны указать после:, находится в корне репозитория git. (это было дано ниже в качестве ответа, но я думаю, что это было задумано как комментарий к этому ответу) - person MatrixFrog; 28.02.2011
comment
Если вы хотите увидеть его в разделе Vim, чтобы они прокручивались вместе, я написал короткий сообщение в блоге, показывающее, как это сделать. - person Flaviu; 25.12.2011
comment
mercurial может обновить все репо до предыдущей версии ... с помощью команды обновления. любой аналогичный способ в git временно переключиться на предыдущую ревизию ?? - person ashishsony; 03.01.2012
comment
@ashishsony: Да, вы можете использовать git checkout <revision>. - person mipadi; 03.01.2012
comment
что происходит с изменениями, которые я делаю в рабочем каталоге ?? есть ли способ сохранить их нетронутыми и вернуть их, как только я вернусь к исправлению? Спасибо. - person ashishsony; 04.01.2012
comment
Спасибо! Какая полезная команда. Я мучительно и неэффективно пытался скопировать, вставить и переформатировать мой старый исходный код из файла diff. - person ratsimihah; 24.07.2012
comment
вы можете использовать git log - [имя_файла], чтобы просмотреть исправления - person Michael Dausmann; 17.02.2014
comment
Вы также можете перенаправить git show в vim, используя (commit):(path to file) | vim -. Я считаю это намного лучше, чем использовать меньше / больше, которое используется по умолчанию. - person laughing_man; 06.03.2014
comment
По какой-то причине единственное, что кажется мне работающим, - это git show <commit>:file Все остальное просто дает самую последнюю версию. - person Bobby Jack; 24.11.2014
comment
Вы сказали, что показывать последнюю четвертую фиксацию файла, но действительно ли вы имели в виду показать файл в том виде, в котором он был в четвертой последней фиксации? - person Craig McQueen; 15.04.2015
comment
Эти инструкции не работают в моем случае. Он может найти файл на диске, но сообщает, что его нет в предоставленной фиксации; однако я получил sha фиксации от git blame, поэтому он должен быть в фиксации. - person weberc2; 10.06.2016
comment
Синтаксис HEAD: ~ ‹n› НЕ работает должным образом. Не отображается n-я предыдущая ревизия файла src / main.c. Он показывает содержимое этого файла на n-й предыдущей фиксации текущей ветки. Если файл src / main.c не изменялся при каждой фиксации в истории ветки, это не даст ожидаемого результата. - person Die in Sente; 07.07.2016
comment
REVISION может быть хешем фиксации. См. Мой ответ: stackoverflow.com/a/40400259/759452 - person Adrien Be; 03.11.2016
comment
git-show отлично. Могу ли я переключать номера строк при использовании в командной строке? - person KFL; 11.01.2017
comment
Чтобы добавить к ответу, git-show не дает вам номеров строк. Если вам нужны номера строк, попробуйте git show <commit>:<file> | less -N - person KFL; 11.01.2017
comment
Вместо того, чтобы указывать путь от корня репо, вы можете использовать относительный путь, если вы начинаете его с ., например: git show HEAD:./subdir/main.c > foo. Это работает в последних версиях git (проверено в git 2.8.3 на CentOS 7) - person Eponymous; 06.09.2017
comment
@MichaelDausmann, я добавил в файл серию патчей, используя git add -p. Есть ли способ увидеть весь файл в том виде, в каком он находится в индексе, прежде чем я его зафиксирую? - person alpha_989; 30.04.2018
comment
Не получается, получаю fatal: Invalid object name 'REVISION'. - person Black; 14.07.2018
comment
@Black: замените REVISION своей фактической ревизией (может быть SHA фиксации Git, имя тега, имя ветки, относительное имя фиксации или любой другой способ идентификации фиксации в Git). - person mipadi; 17.07.2018
comment
@mipadi, не работает Я пробовал: git show 717fe60db378e7052247fa5de33e50bce59e2e85: app \ Models \ Selenium.php Но выхода нет - person Black; 17.07.2018
comment
@Black: Это путь в вашем репозитории? Здесь много чего может пойти не так. - person mipadi; 18.07.2018
comment
Не хотел голосовать за этот ответ, так как теперь у него 1337 голосов. Все равно сделал это :) - person Michel; 10.08.2018
comment
У меня это работает. Я получаю вывод в терминале. Есть ли способ отправить это в текстовый файл? - person Diego; 23.10.2019
comment
@Diego: перенаправить вывод в файл: git show REVISION:path/to/file > path/to/file. - person mipadi; 24.10.2019

Выполнение этого по дате выглядит следующим образом , если фиксация произошла в течение последних 90 дней:

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

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

Это важно! Это означает, что по умолчанию этот метод работает только для истории за последние 90 дней. В противном случае нужно сделать так:

git show $(git rev-list -1 --before="2013-02-26" HEAD):./fileInCurrentDirectory.txt
person Jim Hunziker    schedule 07.03.2013
comment
Эта команда полезна с master вместо HEAD@{2013-02-25}, если вы находитесь в ветке - person funroll; 09.11.2015
comment
Можете ли вы включить время à la git log --since='2016-04-28 23:59:59 +0100'? - person dumbledad; 03.05.2016
comment
Тот факт, что этот синтаксис использует журнал ссылок, важен и должен быть особо подчеркнут, потому что журнал ссылок не содержит всех коммитов. См. blog.endpoint.com/2014/05/git -checkout-at-specific-date.html - person Alice Heaton; 30.12.2016
comment
То, что я пропустил: не может быть пробела после двоеточия : и перед именем файла. - person Abhishek Divekar; 11.01.2018
comment
@AliceHeaton Это невозможно переоценить. (Спасибо !) - person Skippy le Grand Gourou; 25.01.2021
comment
@AliceHeaton - обновлено (4 года спустя, ха-ха!) - person Jim Hunziker; 25.01.2021

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

  1. запустите gitk с:

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

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

    • Click on the "tree" radio button. This will show the root of the file tree at that revision.
    • Перейдите к своему файлу.
person Trausti Kristjansson    schedule 19.12.2012
comment
Это также работает с tig, который является программой просмотра репозитория curses git. - person Matthew G; 13.05.2013
comment
@Paul Slocum: Может быть, потому, что эта команда не является стандартной командой, а не встроенной в git. Я думаю, что эта команда работает только для Windows. - person Envil; 04.12.2013
comment
Обратите внимание, что это работает, только если вы начинаете с корня репозитория git. - person Marc; 23.03.2016
comment
Если вы хотите проверить определенную версию с помощью gitk, вы также можете использовать этот ярлык: gitk REVISION /path/to/file. Это может пригодиться, например, когда вы хотите проверить определенную версию. - person Christian.D; 06.07.2016

Вы также можете указать 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.

person Adrien Be    schedule 03.11.2016
comment
если вы не знаете путь к файлу, используйте git show <SHA1> --name-only, чтобы получить его. - person Tiina; 11.10.2017
comment
эта команда op - даже автоматически завершается из памяти - проверена на удаленном каталоге ... не может получить больше op, чем это gg - person treyBake; 10.11.2017
comment
в debian добавление ./ не имеет значения для пути. - person Timo; 15.08.2020

Помимо ответа Джима Ханзикера,

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

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

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

person Ijas Ameenudeen    schedule 30.04.2014

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

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

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

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

person sachin_ur    schedule 13.12.2018
comment
Эти команды показывают мне различия с текущей версией, но не показывают весь файл. - person Jean Paul; 21.01.2019
comment
Важно отметить, что этот ответ совпадает с вопросом Как показать различия для данного файла в последних фиксациях? вместо Как просмотреть старую версию файла с помощью Git? задает исходный вопрос. - person Mikko Rantalainen; 16.06.2021

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

person sanbor    schedule 06.05.2016
comment
Похоже, git log -pm также покажет коммиты слияния. - person sanbor; 06.05.2016
comment
Вы также можете запустить git log -p -- filename.txt, чтобы ограничить историю только желаемым файлом. - person Jean Paul; 21.01.2019

СПОСОБ 1: (я предпочитаю этот способ, без возможности потери незафиксированных данных)

  1. Найдите идентификатор фиксации с помощью: git reflog

  2. # P3 # # P4 #
    # P5 #
  3. Откройте требуемый файл с помощью следующей команды:

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

    Пример:

    git show d2f9ba4:Src/Ext/MoreSwiftUI/ListCustom.swift
    Src/... - это путь к файлу из шага 2.


СПОСОБ 2: (возможность потерять незафиксированные данные)

  1. Найдите идентификатор фиксации с помощью: git reflog

  2. Сделайте полный сброс этого коммита: git reset --hard %commit ID%

    Пример:

    git reset --hard c14809fa

  3. Внесите необходимые изменения и сделайте новый коммит в нужную ветку

person Andrew    schedule 26.01.2020
comment
ВНИМАНИЕ: будьте осторожны со вторым методом, так как вы потеряете все незавершенные изменения при выполнении аппаратного сброса! - person Enn Michael; 01.12.2020
comment
да, с аппаратным сбросом все в порядке. это из-за сброса жестко, но не мягко. Но нужно усердно работать из-за возможности конфликтов. - person Andrew; 01.12.2020

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

e.g.

git_dump_all_versions_of_a_file.sh path/to/somefile.txt

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

person Brad Parks    schedule 30.10.2017
comment
git_root, git_log_short и git_log_message_for_commit отсутствуют. - person mogsie; 26.01.2018
comment
Хороший улов! Я дважды разместил этот ответ в двух разных местах, а просто удалил его и связал с другим, где люди рассказывали мне об этом раньше ... спасибо @mogsie! - person Brad Parks; 26.01.2018
comment
Этот скрипт очень полезен! - person XMAN; 22.12.2018

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

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

#!/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

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

person Ciro Santilli 新疆再教育营六四事件ۍ    schedule 07.12.2018
comment
@MickeyPerlstein, если вы можете добиться того же интерфейса с лучшей реализацией, я все слышу. - person Ciro Santilli 新疆再教育营六四事件ۍ 24.03.2019
comment
возможно, я не понимаю (и если да, то приношу свои извинения), но разве это не просто: git show version: ./ path ›new_path? - person Mickey Perlstein; 26.03.2019
comment
@MickeyPerlstein привет, да, моя команда генерирует этот интерфейс командной строки, но она перебирает несколько файлов и выдает имя вывода из ввода, так что вам не нужно набирать слишком много. Ничего революционного конечно, но удобно. - person Ciro Santilli 新疆再教育营六四事件ۍ 27.03.2019