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



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



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




  1. каков был бы самый быстрый способ найти фиксацию, которая удалила данное имя файла?

  2. что было бы самым простым способом вернуть этот файл в мою работу понял?


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

1641   19  

19 ответов:

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

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 filename для восстановления удаленного файла.

здесь $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, если , и 1 в противном случае. Команда " run " из 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 ' s ответ (голосуют), и мой собственный ответ о "передайте аргумент команде git alias":

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

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

git restore my_deleted_file

кризис миновал.


Роберт Дэйли предлагает в комментариях следующие псевдонимы:

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

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

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

git checkout -- .

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

git checkout <file_path>

и вуаля, ваш файл обратно.

у меня есть данное решение.

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

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

совершить 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 do:

git checkout bfe68bd117e1091c96d2976c99b3bcc8310bebe7^1 yourDeletedFile.java

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

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 undelete path/to/file.ext

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

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

    git undelete path/to/file.ext
    

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

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

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, мне нужно было восстановить файлы, но затем разархивировать их. У меня были сотни файлов для восстановления, ввод вручную для каждого файла, как и в других примерах, будет слишком медленным.

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 fsck --lost-found

проверьте каждый висячий фиксатор

git reset --hard <commit id>

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

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

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

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

на основе превосходного ответа Чарльза Бейли вот мой один лайнер:

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)

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

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

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

$ git log --diff-filter=D --summary  | grep "delete" | sort

Comments

    Ничего не найдено.