Как восстановиться после «git rm -rf». и по-прежнему сохранять незафиксированные изменения?

У меня была куча изменений, добавленных в промежуточный индекс git add *, но еще не совершил, я хотел их удалить, отменить добавление, поэтому я сделал git rm -rf ., к моему удивлению, они были удалены с моего жесткого диска, мне нужен способ вернуть их; однако я внес огромные изменения, и я хотел бы вернуть эти изменения.

TLDR: Я удалил весь свой проект к git rm -rf ., мне нужно как-то сбросить удаление, чтобы сохранить незафиксированные изменения и вернуть свои файлы. Пожалуйста, я слишком боюсь, что могу потерять весь свой проект.

ОТВЕЧАТЬ: Мой репозиторий — это, по сути, веб-сайт с большим количеством контента. Основываясь на ответах ниже, я сделал 2 копии своего репозитория, назовем их копией А и копией Б, так как ИИ сделал git reset --hard чтобы вернуться к последнему коммиту, я получил мои файлы вернулись, но потеряли внесенные в них изменения. поэтому для копирования BI сделал git fsck --lost-found и перешел в каталог .git/lost-found/other/, который содержал несколько версий моих файлов с хэш-именами, я продолжал открывать каждую из них, это было более 60 файлов, кстати, каждый файл, который я узнаю, я переименовываю его в его фактический name, а затем поместите его вместо более старых версий внутри копии A, в конце я удалил свое исходное репо и теперь использую копию A в качестве своего веб-сайта. это как будто ничего не произошло сейчас. Одна маленькая глупая ошибка => 5 часов боли. Не повторяй того, что я сделал, никогда.

прямо сейчас git status показывает все мои файлы как «удаленные:» и они выделены зеленым цветом.

Я думаю, вам не повезло. Если бы вы набрали rm -rf ., ваши изменения все еще были бы в индексе Git, но с помощью git rm были обновлены и индекс, и рабочая копия на диске. Но на случай, если я ошибаюсь, СДЕЛАЙТЕ КОПИЮ всего каталога проекта, включая каталог .git, прежде чем продолжать экспериментировать.

Thomas 14.06.2019 14:03

Да, я усвоил это на собственном горьком опыте. Если вы возитесь с git, git испортит вас. Правило № 1, которое нужно преподавать на любом из курсов по git, которые я проходил, — СДЕЛАЙТЕ КОПИЮ, ЕСЛИ ВЫ НЕ УВЕРЕНЫ, ЧТО ДЕЛАЕТЕ.

aelmosalamy 14.06.2019 14:07

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

Thomas 14.06.2019 14:08
Коммиты сохраняются навсегда (или, по крайней мере, до тех пор, пока вы все еще можете найти хэш-идентификатор — подробности см. в Думай как (а) Git). Вещи, с которыми вы активно возитесь, в индексе и рабочем дереве, сохраняются нет навсегда.
torek 14.06.2019 17:03
Стоит ли изучать PHP в 2023-2024 годах?
Стоит ли изучать PHP в 2023-2024 годах?
Привет всем, сегодня я хочу высказать свои соображения по поводу вопроса, который я уже много раз получал в своем сообществе: "Стоит ли изучать PHP в...
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
В JavaScript одним из самых запутанных понятий является поведение ключевого слова "this" в стрелочной и обычной функциях.
Приемы CSS-макетирования - floats и Flexbox
Приемы CSS-макетирования - floats и Flexbox
Здравствуйте, друзья-студенты! Готовы совершенствовать свои навыки веб-дизайна? Сегодня в нашем путешествии мы рассмотрим приемы CSS-верстки - в...
Тестирование функциональных ngrx-эффектов в Angular 16 с помощью Jest
В системе управления состояниями ngrx, совместимой с Angular 16, появились функциональные эффекты. Это здорово и делает код определенно легче для...
Концепция локализации и ее применение в приложениях React ⚡️
Концепция локализации и ее применение в приложениях React ⚡️
Локализация - это процесс адаптации приложения к различным языкам и культурным требованиям. Это позволяет пользователям получить опыт, соответствующий...
Пользовательский скаляр GraphQL
Пользовательский скаляр GraphQL
Листовые узлы системы типов GraphQL называются скалярами. Достигнув скалярного типа, невозможно спуститься дальше по иерархии типов. Скалярный тип...
2
4
605
5
Перейти к ответу Данный вопрос помечен как решенный

Ответы 5

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

Вы можете вернуть сохраненные файлы с помощью git reset --hard HEAD. Поскольку вы очистили свое промежуточное дерево, ваши незафиксированные изменения больше не находятся в git (как указывают несколько других ответов, это может быть неправдой), поэтому ваш единственный шанс их восстановить - это любые резервные копии, которые вы или ваша ОС могли сделать.

Мне жаль, что это не поможет в текущей ситуации, но для дальнейшего использования вы можете отменить свои изменения с помощью git reset HEAD.

Насколько я знаю, git add * перемещает изменения из рабочего каталога в промежуточный индекс, git rm --cached делает наоборот, а git commit перемещает изменения из промежуточного индекса в репозиторий .git, что делает git reset? что мне не хватает?

aelmosalamy 14.06.2019 14:27
git reset --hard HEAD установит вершину вашего промежуточного дерева на вершину вашей текущей ветки, а также извлечет все файлы из вашей текущей ветки. Это сбросит все до вашего последнего коммита.
Calum Halpin 14.06.2019 14:30
git rm --cached делает не то, что вы думаете. Используйте git reset <file>, чтобы удалить файл из индекса, но не из вашего рабочего каталога.
Khoyo 14.06.2019 14:30

Спасибо, что прояснили некоторую информацию или, точнее: «раскрыли тайну».

aelmosalamy 14.06.2019 14:58

Для файлов, которые были зафиксированы, git reset --hard восстановит их все.

Для тех, кто добавлен, но не зафиксирован, попробуйте git fsck --lost-found. Он будет печатать висячие капли и делать их копии в .git/lost-found/other. Вы можете запустить git cat-file -p $blob или cat .git/lost-found/other/$blob, чтобы увидеть содержимое. Блобы не записывают пути к файлам, поэтому вам необходимо сопоставить содержимое и путь к файлу по памяти или по ключевому слову, которое не было недавно изменено с помощью git grep $keyword. После того, как вы узнаете путь к большому двоичному объекту, запустите cp .git/lost-found/other/$blob $path, чтобы восстановить его.

С использованием

find .git/objects/ -type f -printf "%T+\t%p\n" \
  | sort \
  | sed 's:.*git/objects/\(.*\)/\(.*\):\1\2:' \
  | while read object; do
       echo -n "$object "; 
       git cat-file -t "$object";
    done

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

Например, в тестовом репо:

908553f63e9126f933b690970d41adc3377e3360 blob
31e0d0e213c9976308fbb91c542ced9218fa8f6a tree
5b181f91c49d287b4670fcf3545656dc0c0ef5f4 commit
de683137e0b2d0a40f766307e81999986e4b31c2 blob
086cb344a4fd8a9d671006b8e5844f2437faa3ab tree
930ba9809b5d50410b72c3fbff111d948f1027fa commit
e69de29bb2d1d6434b8b29ae775ad8c2e48c5391 blob
40cda8e010466dc7a4a0eb107e7e45804290685e blob

Последние два больших двоичных объекта были созданы после последней фиксации, и если вы напечатаете их, например. git cat-file -p 40cda8e010466dc7a4a0eb107e7e45804290685e, вы сможете восстановить содержимое файла.

Вы также можете получить некоторые деревья таким образом (используйте git ls-tree <tree-id>, чтобы напечатать их), но не дерево верхнего уровня, так как оно было сохранено непосредственно в индексе.

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

aelmosalamy 14.06.2019 14:31
Ответ принят как подходящий

Может быть надежда: объекты, которые вы ранее добавили в индекс, могут все еще существовать, хотя на них больше не ссылаются. Для проверки я сделал следующее:

$ git init test
$ cd test
$ echo hello > README.md
$ git add README.md
$ git commit -m"Add README.md"
$ echo world >> README.md
$ cat README.md
hello
world
$ git add README.md
$ git rm -f README.md
$ git status
On branch master
Changes to be committed:
  (use "git reset HEAD <file>..." to unstage)

        deleted:    README.md

$ git fsck
Checking object directories: 100% (256/256), done.
unreachable blob 94954abda49de8615a048f8d2e64b5de848e27a1
$ git show 94954abda49de8615a048f8d2e64b5de848e27a1
hello
world

Таким образом, даже после git rm -f содержимое файла, добавленное в индекс, все еще существует. Вы можете сбросить их все в .git/lost-found/other, запустив git fsck --lost-found.

Сам индекс не хранится как объект Git, а находится непосредственно в .git/index, поэтому я думаю, что он был безвозвратно перезаписан. Это означает, что пути к файлам, а также любые метаданные, такие как разрешения, были потеряны.

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

aelmosalamy 14.06.2019 14:48

То, как вы воссоздали проблему, гениально, приветствую вас!

aelmosalamy 14.06.2019 16:40

git status подсказывает, какие команды можно использовать для восстановления файлов:

$ git rm  -rf .
$ git status

On branch master
Your branch is up to date with 'origin/master'.

Changes to be committed:
  (use "git reset HEAD <file>..." to unstage)

  deleted: file1
  deleted: file2

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

$ git reset HEAD file1 file2
$ git status

On branch master
Your branch is up to date with 'origin/master'.

Changes not staged for commit:
  (use "git add/rm <file>..." to update what will be committed)
  (use "git checkout -- <file>..." to discard changes in working directory)

    deleted:    file1
    deleted:    file2

no changes added to commit (use "git add" and/or "git commit -a")

Проверьте удаленные файлы:

$ git checkout -- file1 file2
$ git status
On branch master
Your branch is up to date with 'origin/master'.

nothing to commit, working tree clean

Вы спасли мою жизнь

Ruzaik Nazeer 23.05.2021 15:19

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