У меня была куча изменений, добавленных в промежуточный индекс 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
показывает все мои файлы как «удаленные:» и они выделены зеленым цветом.
Да, я усвоил это на собственном горьком опыте. Если вы возитесь с git, git испортит вас. Правило № 1, которое нужно преподавать на любом из курсов по git, которые я проходил, — СДЕЛАЙТЕ КОПИЮ, ЕСЛИ ВЫ НЕ УВЕРЕНЫ, ЧТО ДЕЛАЕТЕ.
Если подумать дальше, может случиться так, что предыдущая версия индекса или, по крайней мере, файлы, которые в нем содержались, все еще находятся в виде больших двоичных объектов в вашем репозитории. Надеюсь, кто-то, кто больше разбирается в этом, откликнется.
Первое, что вы должны сделать, как сказали комментаторы, это сделать резервную копию каталога вашего проекта.
Вы можете вернуть сохраненные файлы с помощью git reset --hard HEAD
. Поскольку вы очистили свое промежуточное дерево, ваши незафиксированные изменения больше не находятся в git (как указывают несколько других ответов, это может быть неправдой), поэтому ваш единственный шанс их восстановить - это любые резервные копии, которые вы или ваша ОС могли сделать.
Мне жаль, что это не поможет в текущей ситуации, но для дальнейшего использования вы можете отменить свои изменения с помощью git reset HEAD
.
Насколько я знаю, git add *
перемещает изменения из рабочего каталога в промежуточный индекс, git rm --cached
делает наоборот, а git commit
перемещает изменения из промежуточного индекса в репозиторий .git, что делает git reset
? что мне не хватает?
git reset --hard HEAD
установит вершину вашего промежуточного дерева на вершину вашей текущей ветки, а также извлечет все файлы из вашей текущей ветки. Это сбросит все до вашего последнего коммита.
git rm --cached
делает не то, что вы думаете. Используйте git reset <file>
, чтобы удалить файл из индекса, но не из вашего рабочего каталога.
Спасибо, что прояснили некоторую информацию или, точнее: «раскрыли тайну».
Для файлов, которые были зафиксированы, 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>
, чтобы напечатать их), но не дерево верхнего уровня, так как оно было сохранено непосредственно в индексе.
Пока это самый полезный ответ, я немного побалуюсь с ним и дам вам знать.
Может быть надежда: объекты, которые вы ранее добавили в индекс, могут все еще существовать, хотя на них больше не ссылаются. Для проверки я сделал следующее:
$ 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, которые вы выполняете, это не называется контроль версий просто так.
То, как вы воссоздали проблему, гениально, приветствую вас!
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
Вы спасли мою жизнь
Я думаю, вам не повезло. Если бы вы набрали
rm -rf .
, ваши изменения все еще были бы в индексе Git, но с помощьюgit rm
были обновлены и индекс, и рабочая копия на диске. Но на случай, если я ошибаюсь, СДЕЛАЙТЕ КОПИЮ всего каталога проекта, включая каталог.git
, прежде чем продолжать экспериментировать.