Восстановление добавленного файла после выполнения git reset --hard HEAD^

Я добавил новый файл F1 и внес изменения в другой файл F2, но затем сделал "git reset --hard HEAD^", и я потерял все изменения в файлах.

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

Я посмотрел на связанный с этим вопрос здесь: Как я могу отменить git reset --hard HEAD~1? но этот вопрос предполагает, что тот сделал git commit.

6 ответов

Решение

Вы можете (с некоторой работой) восстановить состояние файла при последнем "git add ". Ты можешь использовать

$ git fsck --cache --no-reflogs --lost-found --unreachable  HEAD

а затем проверьте файлы в каталоге.git/lost-found/other.

Пожалуйста, прочитайте страницу руководства git fsck.

(Я предполагаю, что отсутствующий файл не является частью какого-либо коммита. В противном случае, git log --all -g --diff-filter=D --stat твой друг.)

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

    git fsck --unreachable --no-reflogs --no-cache HEAD | fgrep " tree " \
    | cut -d " " -f3 | xargs -r -n1 git ls-tree \
    | fgrep " blob " | cut -d " " -f 3- | sort -k2 -u
    
  2. Если вы видите что-то интересное, git cat-file blob SHA-1-of-interesting-file выведет файл на стандартный вывод. (Пример: git cat-file blob b8f0bdf56 > recovered-logo.png)

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

Если отсутствующий файл никогда не ставился (git stage или же git add) или прятать (git stash), вам почти не повезло, потому что, насколько git знает, файл никогда не существовал. (Вы все еще можете попробовать сделать git fsck --no-reflogs --lost-found и осматриваться в каталоге .git/lost-found/other чтобы узнать, есть ли у вас что-то, что стоит сохранить на тот случай, если в git действительно есть копия вашего пропавшего файла в результате случайности. У вас нет имен файлов, чтобы помочь вам в этом случае, только содержимое файла.)

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

gitk --all $( git fsck | awk '/dangling commit/ {print $3}'; git log -g --pretty='format:%H' )

Это будет работать gitk со всеми ветками, всеми reflog и всеми висячими коммитами. Вы можете добавить -n 10000 или какое-то другое ограничение в случае, если в вашем репо действительно много коммитов (скажем, в ядре Linux). Если у вас нет gitkвместо этого вы можете запустить меньшую версию, используя только командную строку:

git log --all --decorate --stat --graph --date-order $( git fsck | awk '/dangling commit/ {print $3}'; git log -g --pretty='format:%H' )

или версия с менее подробным выводом

git log --all --decorate --oneline --graph --date-order $( git fsck | awk '/dangling commit/ {print $3}'; git log -g --pretty='format:%H' )

Если вы видите коммит, который хотите сохранить как ветку recovered1просто делай git checkout -b recovered1 <sha1-of-the-commit>,

Попробуйте это http://gitready.com/advanced/2009/01/17/restoring-lost-commits.html

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

E сть git plugin это делает это из коробки:

https://github.com/pendashteh/git-recover-index

$ cd /path/to/disatered/repo
$ git clone git@github.com:pendashteh/git-recover-index.git $HOME/.git-recover-index
$ $HOME/.git-recover-index/git-recover-index.sh

На самом деле, если вы добавили объект в индекс (с помощью git add), для этого состояния объекта создается большой двоичный объект, но нет объекта дерева (и, следовательно, фиксации), который ссылается на него. Вот как можно получить "болтающийся" свободный объектный файл, и если вы запустите git fsck, он покажет вам не имеющий ссылки BLOB-объект (git gc удалит эти типы объектов, если он будет запущен).

По этой причине вы можете использовать reflog, если он у вас включен, чтобы попытаться восстановить состояние индекса для добавленного вами файла F1. Если вы вообще не добавили F2, то, как сказал Грег, git ничего об этом не знает, и вам не повезло.

Если вы используете VSCode, вы можете использовать функцию Timetime (щелкнув правой кнопкой мыши измененный файл и выбрав «Открыть временную шкалу»)

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