Восстановить файл из старого коммита в git

188

У меня есть старый коммит, который я сделал несколько недель назад. Я хочу восстановить только один файл из этого коммита. Что мне делать?

Варун Ахар
источник

Ответы:

222
git checkout 'master@{7 days ago}' -- path/to/file.txt

Это не изменит HEAD, оно просто перезапишет локальный файл path/to/file.txt

Смотрите man git-rev-parse для возможных спецификаций ревизий (конечно, простой хеш (вроде бы dd9bacb) подойдет)

Не забудьте зафиксировать изменение (после проверки ...)

sehe
источник
15
Ух ты, @heneryville и sehe, я на самом деле думал, что «7 дней назад» - это мета, потому что ты определишь, что совершить. ти!
AnneTheAgile
7
Часть 2 При желании выбрать конкретный коммит вышеуказанный формат не работает. Вместо этого используйте то, что Urs показал ниже, git checkout commitShaNumber - путь / к / file.txt для каждого stackoverflow.com/questions/215718/…
AnneTheAgile
2
@AnneTheAgile в том , что до сих пор точно такой же синтаксис, я только что произошло , чтобы дать «сложный» пример , revision-specificationтак это то , что просили ОП :)
sehe
1
Если ваш коммит был использован для удаления файла, который вы пытаетесь восстановить, просто используйте shacommit~1(ex:), git checkout 0f4bbdcd~1 -- path/to/file.txtчтобы получить коммит непосредственно перед этим.
Сдлинс
90
  1. Проверьте файл из вашего старого коммита через git checkout [Revision_Key] -- path/to/file.
  2. Добавить, зафиксировать, нажать в зависимости от обстоятельств.
Урс Рупке
источник
3
git checkoutможет обрабатывать отдельные файлы (см. ответ по sehe), не нужно копировать и вставлять.
Корактор
1
Всегда ли ключи ревизии SHA1 для фиксации?
IslandCow
1
Они есть, но обычно первых 6–8 символов SHA1 достаточно для идентификации ревизии.
Урс Рупке
2
@IslandCow нет, они могут быть sha1 , но и ветви, теги, или любая другая вещь , которая указывает на фиксацию, например HEAD, ORIG_HEADили любой из них в сочетании с ^/ ~/ @-style нотации.
Алоис Махдал
2
Вы указываете, что впоследствии предполагается «добавить» файл. Но это неверно. Файл не помещается в промежуточную область. Это уже добавлено.
xApple
10

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

  1. git log -3
    Это показывает три последних коммитов. Прочитайте комментарии и имя автора, чтобы определить, какую именно версию вы хотите. Запишите этот длинный идентификатор (например b6b94f2c19c456336d60b9409fb1e373036d3d71) для версии коммита, которую вы хотите.

  2. git checkout b6b94f2c19c456336d60b9409fb1e373036d3d71 -- myfile.java
    Передайте идентификатор фиксации И имя файла, который вы хотите восстановить. Убедитесь, что у вас есть пробел до и после двойного дефиса.

Есть много других способов сделать это, но это самый простой, который я могу вспомнить.

ПРИМЕЧАНИЕ. Если вы находитесь внутри пути / папки вашего проекта, то нет необходимости вводить полный путь к файлу в команде извлечения.

Сальвадор Валенсия
источник
Лучший комментарий когда-либо. Поскольку тот, который является принятым ответом, предполагает, что файл, который должен быть извлечен, передается вверх по потоку, однако эта команда извлекает / восстанавливает файл, который существует только локально.
ot0
1
Только что попробовал это в корневой папке моего локального репозитория git. Мне все еще нужно было указать относительный путь к файлу. Простое предоставление - [имя файла] само по себе не сработало.
user2784627
@ ot0 Нет, это не так. Они точно такой же ответ.
Мэтт
4

Все ответы упоминаются git checkout <tree-ish> -- <pathspec>. Начиная с git v2.23.0, появился новый метод восстановления git, который должен принять на себя часть git checkoutответственности. Смотрите основные изменения в блоге GitHub .

Поведение этой команды по умолчанию заключается в восстановлении состояния рабочего дерева с содержимым, полученным из sourceпараметра (который в вашем случае будет хешем коммита).

Предполагая, что коммит хеш это abcdefкоманда будет выглядеть так:

git restore --source=abcdef file_name

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

git restore --source=abcdef --worktree --staged file_name

или с короткими именами опций:

git restore -s=abcdef -W -S file_name
mjarosie
источник