Подтвердить что ты не робот

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

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

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

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

4b9b3361

Ответ 1

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

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

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

Прочитайте git fsck manpage.

Ответ 2

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

  • Получить список недостижимых файлов, которые 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
    
  • Если вы видите что-то интересное, 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 kernel). Если у вас нет 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' )

Ответ 4

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

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