Найти и восстановить удаленный файл в репозитории Git

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

Я знаю, что могу оформить заказ, используя файл git checkout HEAD^ foo.bar, но я не знаю, когда этот файл был удален.

  1. Какой самый быстрый способ найти коммит, который удалил данное имя файла?
  2. Что было бы самым простым способом вернуть этот файл в мою рабочую копию?

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

31 ответ

Решение

Найдите последний коммит, который затронул данный путь. Поскольку файл не находится в коммите HEAD, этот коммит, должно быть, удалил его.

git rev-list -n 1 HEAD -- <file_path>

Затем проверьте версию при коммите, используя каретку (^) условное обозначение:

git checkout <deleting_commit>^ -- <file_path>

Или в одной команде, если $file это файл в вопросе.

git checkout $(git rev-list -n 1 HEAD -- "$file")^ -- "$file"

Если вы используете zsh и у вас включена опция EXTENDED_GLOB, символ каретки не будет работать. Ты можешь использовать ~1 вместо.

git checkout $(git rev-list -n 1 HEAD -- "$file")~1 -- "$file"
  1. использование git log --diff-filter=D --summary получить все коммиты, которые удалили файлы и файлы удалены;
  2. использование git checkout $commit~1 path/to/file.ext восстановить удаленный файл.

куда $commit это значение коммита, которое вы нашли на шаге 1, например e4cf499627

Чтобы восстановить все эти удаленные файлы в папке, введите следующую команду.

git ls-files -d | xargs git checkout --

Я пришел к этому вопросу, пытаясь восстановить файл, который только что удалил, но еще не внес изменения. На случай, если вы окажетесь в такой ситуации, все, что вам нужно сделать, это следующее:

git checkout HEAD -- path/to/file.ext

Если вы ненормальный, используйте git-bisect, Вот что нужно сделать:

git bisect start
git bisect bad
git bisect good <some commit where you know the file existed>

Теперь пришло время запустить автоматический тест. Команда оболочки '[ -e foo.bar ]' вернет 0, если foo.bar существует, и 1 в противном случае. Команда "запустить" git-bisect будет использовать бинарный поиск, чтобы автоматически найти первый коммит, где тест не пройден. Он начинается на полпути через заданный диапазон (от хорошего до плохого) и разрезает его пополам в зависимости от результата указанного теста.

git bisect run '[ -e foo.bar ]'

Теперь вы в коммите, который удалил его. Отсюда вы можете вернуться в будущее и использовать git-revert отменить изменения,

git bisect reset
git revert <the offending commit>

или вы можете вернуться на один коммит и вручную осмотреть повреждения:

git checkout HEAD^
cp foo.bar /tmp
git bisect reset
cp /tmp/foo.bar .

Мой новый любимый псевдоним, основанный на ответе bonyiii (upvoted) и моем собственном ответе о " Передать аргумент команде псевдонима Git ":

git config alias.restore '!f() { git checkout $(git rev-list -n 1 HEAD -- $1)~1 -- $(git diff --name-status $(git rev-list -n 1 HEAD -- $1)~1 | grep '^D' | cut -f 2); }; f'

Я потерял файл, удаленный по ошибке несколько коммитов назад?
Быстрый:

git restore my_deleted_file

Кризис предотвращен.


void.pointer предлагает в комментариях следующий псевдоним:

restore-file = !git checkout $(git rev-list -n 1 HEAD -- "$1")^ -- "$1"

И jegan добавляет в комментариях:

Для установки псевдонима из командной строки я использовал эту команду:

git config --global alias.restore "\!git checkout \$(git rev-list -n 1 HEAD -- \"\$1\")^ -- \"\$1\"" 

Если вы знаете имя файла, это простой способ с основными командами:

Перечислите все коммиты для этого файла.

git log -- path/to/file

Последний коммит (самый верхний) - это тот, который удалил файл. Так что вам нужно восстановить второй до последнего коммита.

git checkout {second to last commit} -- path/to/file

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

git reset HEAD some/path
git checkout -- some/path

Он был протестирован на Git версии 1.7.5.4.

У меня есть это решение.

  1. Получить идентификатор коммита, в котором был удален файл, одним из следующих способов.

    • git log --grep=*word*
    • git log -Sword
    • git log | grep --context=5 *word*
    • git log --stat | grep --context=5 *word* # рекомендуется, если вы ничего не помните
  2. Вы должны получить что-то вроде:

commit bfe68bd117e1091c96d2976c99b3bcc8310bebe7 Автор: Александр Орлов Дата: чт 12 мая 23:44:27 2011 +0200

replaced deprecated GWT class
- gwtI18nKeySync.sh, an outdated (?, replaced by a Maven goal) I18n generation script

commit 3ea4e3af253ac6fd1691ff6bb89c964f54802302 Автор: Александр Орлов Дата: Чт, 12 мая 22:10:22 2011 +0200

3 Теперь, используя идентификатор фиксации bfe68bd117e1091c96d2976c99b3bcc8310bebe7, сделайте:

git checkout bfe68bd117e1091c96d2976c99b3bcc8310bebe7^1 yourDeletedFile.java

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

Если вы только внесли изменения и удалили файл, но не зафиксировали его, а теперь вы расстались со своими изменениями

git checkout -- .

но ваши удаленные файлы не вернулись, вы просто выполните следующую команду:

git checkout <file_path>

И до того, ваш файл вернулся.

На самом деле, этот вопрос непосредственно о Git, но кто-то вроде меня работает с такими инструментами GUI, как WebStorm VCS кроме знания о мерзавце cli команды.

Я щелкаю правой кнопкой мыши на пути, который содержит удаленный файл, а затем перейти к Git а затем нажмите на Show History,

Инструменты VCS показывают все изменения, и я вижу все изменения и изменения каждого из них.

Затем я выбираю коммиты, которые мой друг удаляет PostAd.js файл. теперь смотрите ниже:

И теперь я вижу свое желание удалить удаленный файл. Я просто дважды щелкаю по имени файла, и оно восстанавливается.

Я знаю, что мой ответ не Git Команды, но это быстро, надежно и легко для начинающих и профессиональных разработчиков. Инструменты Webstorm VCS великолепны и идеально подходят для работы с Git и не нуждается ни в каком другом плагине или инструментах.

git undelete path/to/file.ext

  1. Поместите это в свой .bash_profile (или другой соответствующий файл, который загружается при открытии командной оболочки):

    git config --global alias.undelete '!sh -c "git checkout $(git rev-list -n 1 HEAD -- $1)^ -- $1" -'
    
  2. Тогда используйте:

    git undelete path/to/file.ext
    

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

git checkout /path/to/deleted.file

Во многих случаях может быть полезно использовать coreutils (grep, sed и т. Д.) В сочетании с Git. Я уже достаточно хорошо знаю эти инструменты, но Git меньше. Если бы я хотел выполнить поиск удаленного файла, я бы сделал следующее:

git log --raw | grep -B 30 $'D\t.*deleted_file.c'

Когда я нахожу ревизию / коммит:

git checkout <rev>^ -- path/to/refound/deleted_file.c

Так же, как другие заявили до меня.

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

У меня такой же вопрос. Не зная этого, я создал оборванный коммит.

Список свисающих коммитов

git fsck --lost-found

Осмотрите каждый висячий коммит

git reset --hard <commit id>

Мои файлы снова появились, когда я перешел на висячий коммит.

git status по причине:

“HEAD detached from <commit id where it detached>”

Найдите фиксацию, которая удалила ваш файл:

git log --diff-filter=D --oneline -- path/to/file | cut -f -d ' '

Пример вывода:

4711174

Начиная с Git 2.23, на самом деле есть restoreкоманда. Это все еще экспериментально, но чтобы восстановить то, что вы удалили при фиксации (в данном случае 4711174), вы можете ввести:

git restore --source=4711174^ path/to/file

Обратите внимание на ^ после идентификатора фиксации, поскольку мы хотим восстановить что-то из фиксации перед тем, который удалил файл.

В --source аргумент говорит restore команда, где искать файл (ы) для восстановления, и это может быть любой коммит и даже индекс.

См.: git-restore doc для git 2.23.0

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

git show <rev> --diff-filter=D --summary --name-only --no-commit-id | xargs git checkout <rev>^ -- 
git show <rev> --diff-filter=D --summary --name-only --no-commit-id | xargs git reset HEAD 

(Обратите внимание на завершающий пробел в конце каждой команды.)

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

Плюс: приведенные ниже методы хорошо работают в сценарии, когда файлы / папки были удалены даже из корзины или корзины.

Файлы / папки удаляются из рабочего дерева, но еще не зафиксированы:

I. Если вы еще не проиндексировали (git add) свои изменения, вы можете вернуть содержимое каталога:

git restore -- path/to/folder_OR_file

II. Если удаление уже проиндексировано, вы должны сначала сбросить его:

git reset -- path/to/folder_OR_file

затем выполнить, git restore path/to/folder_OR_file

Файлы / папки удаляются в некоторых коммитах в прошлом:

  1. Использовать  git log --diff-filter=D --summary чтобы получить подробную информацию о коммитах, в которых были удалены файлы / папки;
  2. Использовать  git checkout $commit~1 path/to/folder_OR_file для восстановления удаленных файлов / папки. Где  $commit - значение sha фиксации, найденной на шаге 1, например c7578994

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

Основываясь на превосходном ответе Чарльза Бейли, вот мой единственный вкладыш:

git co $(git rev-list -n 1 HEAD -- <file_path>)~1 -- $(git diff --name-status $(git rev-list -n 1 HEAD -- <file_path>)~1 head | grep '^D' | cut -f 2)
user@bsd:~/work/git$ rm slides.tex
user@bsd:~/work/git$ git pull 
Already up-to-date.
user@bsd:~/work/git$ ls slides.tex
ls: slides.tex: No such file or directory

Восстановите удаленный файл:

user@bsd:~/work/git$ git checkout
D       .slides.tex.swp
D       slides.tex
user@bsd:~/work/git$ git checkout slides.tex 
user@bsd:~/work/git$ ls slides.tex
slides.tex

Лучший способ сделать это - попробовать.


Сначала найдите идентификатор коммита, который удалил ваш файл. Он предоставит вам сводку коммитов, которые удалили файлы.

git log --diff-filter=D --сводка

git checkout 84sdhfddbdddf~1

Примечание: 84sdhfddbddd твой commit id

Благодаря этому вы можете легко восстановить все удаленные файлы.

Если вы знаете коммит, который удалил файл (ы), выполните эту команду где <SHA1_deletion> это коммит, который удалил файл:

git diff --diff-filter=D --name-only <SHA1_deletion>~1 <SHA1_deletion> | xargs git checkout <SHA1_deletion>~1 --

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

Это самое простое решение, которое я нашел, если вы хотите просто восстановить тот же файл в мастере:

      git checkout master -- path/to/File.java

Простой и точный

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

git log 

Допустим, вы нашли $commitid 1234567..., затем

git checkout <$commitid> $fileName

Это восстановит версию файла, которая была в этом коммите.

Ты всегда мог git revertваш коммит, который удалил файл. (Предполагается, что удаление было единственным изменением в фиксации.)

> git log
commit 2994bda49cd97ce49099953fc3f76f7d3c35d1d3
Author: Dave <dave@domain.com>
Date:   Thu May 9 11:11:06 2019 -0700

    deleted readme.md

И если вы продолжили работу и позже поняли, что не хотите фиксировать эту фиксацию удаления, вы можете отменить ее, используя:

> git revert 2994bd

Сейчас git log показывает:

> git log
Author: Dave <dave@domain.com>
Date:   Thu May 9 11:17:41 2019 -0700

    Revert "deleted readme"

    This reverts commit 2994bda49cd97ce49099953fc3f76f7d3c35d1d3.

А также readme.md восстановлен в репозиторий.

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

git checkout <file path with name>

Приведенный ниже пример работает для меня:

git checkout resources/views/usaSchools.blade.php

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

$ git checkout -- <file>

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

$ git ls-files --deleted

Если удаление было зафиксировано, найдите фиксацию, в которой это произошло, затем восстановите файл из этой фиксации.

$ git rev-list -n 1 HEAD -- <file>
$ git checkout <commit>^ -- <file>

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

$ git log --diff-filter=D --summary

Вы можете проверить удаленные файлы:

      git checkout

Выход

      D       index.html

Чтобы его восстановить:

      git restore index.html

Если вы удалили несколько файлов и вам нужно восстановить все использование:

      git restore .

См. Изображение в формате Gif

Два способа показать удаленные файлы

Первый способ

git checkout

второй способ

git status -s |grep d

grep d, чтобы показать только удаленные файлы

Чтобы восстановить его, напишите эту команду

git checkout .

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

Или восстановите по имени файла

git checkout -- filename

Чтобы восстановить все удаленные файлы с помощью Git, вы также можете:

git checkout $(git ls-files --deleted)

куда git ls-files --deleted перечисляет все удаленные файлы и git checkout $(git command) восстанавливает список файлов в параметре.

Другие вопросы по тегам