2012-05-28 2 views
9

Я добавил некоторые файлы в индекс, но потом по ошибке я удалил их с помощью git reset --hard. Как восстановить их? Вот что получилось:Восстановить файлы, которые были добавлены в индекс, но затем удалены с помощью сброса git

  1. Я добавил все файлы с помощью git add .
  2. тогда я совершил
  3. Когда я проверил состояние, были все еще файлы, которые не были включены в коммит из оных, который был странно
  4. Я добавил неотслеживаемые файлы снова и он работал на этот раз
  5. Но я хотел, чтобы все было в 1 одну фиксацию, так что я посмотрел, как убрать из буфера, что я только что совершил
  6. Я использовал git reset --hard HEAD^ - плохая идея, очевидно, все файлы были удалены
  7. так, то я использовал git reflog, чтобы найти, где я остановился
  8. тогда я использовал git reflog ______, чтобы вернуться к моей последней фиксации.
  9. , тогда я использовал git reset HEAD, чтобы отключить фиксацию (что я должен был сделать изначально), но файлы, которые я добавил (см. Выше) после фиксации, по-прежнему исчезли.

Как вернуть эти файлы?

+0

Если бы они не были совершены, и вы сбросить индекс прочь, вероятно, вы не сможете. – Ashe

+0

Есть ли способ отменить сброс индекса? –

+1

Вам может повезти, запустив 'git fsck -full' и немного терпения, просеивая все эти недостижимые капли, которые он собирается сообщить. – knittl

ответ

20

Сначала сделайте полную резервную копию своего хранилища Git!

Когда вы создадите файл git add, git создаст blob из этого содержимого и добавит его в свою базу данных объектов (.git/objects/??/*).

Давайте посмотрим на ваши команды, один на один:

Я добавил все файлы с помощью Git добавить.

$ git add . 

Это добавит все файлы, содержащиеся в текущем каталоге и его подкаталогах в базу данных объектов Git и. Неотслеживаемые файлы, соответствующие шаблонам от .gitignore файлов, не будут добавлены. Файлы деревьев также будут записаны. Пожалуйста, см. Конец моего ответа.

я тогда совершил

$ git commit -m'added all files' 

Это запишет новый объект коммита в базу данных объекта. Эта фиксация будет ссылаться на одно дерево. Дерево ссылается на blobs (файлы) и другие деревья (подкаталоги).

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

$ git status 

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

Я добавил неотслеживаемые файлы снова и он работал на этот раз

$ git add . 

Я предполагаю, что вы снова использовали тот же add команду, как в шаге 1.

Но я хотел все, чтобы быть в одном одиночном деле, поэтому я посмотрел, как отключить то, что я только что совершил.

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

я мерзавец сброс --hard ГОЛОВЫ^- плохая идея, очевидно, все файлы были удалены

$ git reset --hard HEAD^ 

Эта команда установит текущее рабочее дерево и индекс, чтобы быть точно фиксации HEAD^ (второй последней фиксации). Другими словами, он будет отбрасывать любые локальные незафиксированные изменения и переместить указатель ветвления назад на один фиксатор. Он не трогает файлы без следа.

так, то я использовал GIT reflog, чтобы найти, где я остановился

$ git reflog 

Это показывает последние коммиты, которые были недавно разрегистрированы (идентичные git reflog HEAD). Если вы укажете имя филиала, оно покажет вам последние коммиты, на которые эта ветвь указала недавно.

тогда я использовал GIT reflog __ вернуться к моей последней фиксации.

Не уверен в этом. git reflog является (в основном) командой только для чтения и не может использоваться для «возврата» к фиксации. Вы можете использовать его, чтобы найти фиксацию ветки (или HEAD), на которую указывает.

затем я использовал git reset HEAD, чтобы отключить фиксацию (что я должен был сделать изначально), но файлы, которые я добавил (см. Выше) после фиксации, по-прежнему отсутствуют. $ сброса мерзавец ГОЛОВА

Это не убрать из буфера это совершить, но это все убрать из буфера поставил (но незавершенных) изменения из индекса. Первоначально (1-й шаг) вы хотели сказать git reset HEAD^ (или git reset --mixed HEAD^) - это оставит ваше рабочее дерево нетронутым, но установите индекс в соответствии с деревом, на которое указывает команда, названная HEAD^.


Теперь, чтобы получить назад ваши файлы, вы должны использовать git fsck --full --unreachable --no-reflog. Он будет сканировать все объекты в базе данных объектов Git и выполнять анализ достижимости. Вы хотите найти blob объектов.Там также должен быть tree объект, описывающий состояние после второго git add .

git cat-file -p <object hash> будет печатать содержимое файлов, так что вы можете убедиться, что у вас есть правильные объекты. Для blobs вы можете использовать перенаправление ввода-вывода для записи содержимого в правильное имя файла. Для деревьев вам нужно использовать команды git (git read-tree). Если это всего лишь несколько файлов, вам лучше писать их непосредственно в файлы.


Несколько замечаний здесь:

Если вы хотите добавить файлы к последней фиксации (или изменить его коммита), вы можете просто использовать git commit --amend. Это в основном обертка вокруг git reset --soft HEAD^ && git commit -c [email protected]{1}.

Также практически не рекомендуется использовать git add .. Обычно вы хотите использовать его только в первый раз, когда вы создаете новый репозиторий. Лучшими альтернативами являются git add -u, git commit -a, в которых будут внесены все изменения в отслеживаемые файлы. Чтобы отслеживать новые файлы, лучше укажите их явно.

+0

Большое вам спасибо. Я попробую это сейчас. –

+0

ДА! У каждого блоба отсутствовал код. Вы должны разместить свой собственный блог Git. Спасибо, что нашли время, чтобы помочь мне, высоко оценили. –

+1

Life saver ... большое спасибо: D – c0deNinja

14

У меня была аналогичная проблема, но у меня было много обвисших капель и деревьев в моем репо, поэтому я закончил фильтрацию с помощью grep вывода всех оборванных капель и печати тех, которые совпадали. Предполагая, что ${UNIQUE_CODE} является некоторый код, который является уникальным для файлов, которые вы имели в индексе, то это должно дать вам хэши сгустков вы ищете:

for b in $(git fsck --lost-found | grep blob | awk '{print $3}'); do git cat-file -p $b | grep -q ${UNIQUE_CODE} && echo $b; done 
+0

Спасибо, человек, Он спас мой день! Однако для восстановления я сделал следующее: для b в $ (git fsck --lost-found | grep blob | awk '{print $ 3}'); do git cat-file -p $ b> ../$b; сделанный –