如何从 "git rm -rf ." 中恢复并仍然保留未提交的更改?
How to recover from "git rm -rf ." and still retain uncomitted changes?
git add *
、我对暂存索引添加了一堆更改,但尚未提交,我想删除它们,撤消添加 ,所以我做了 git rm -rf .
令我惊讶的是它从我的硬盘驱动器中删除了它们,我想要一种方法来恢复它们;但是,我已经进行了巨大的更改,我想恢复这些更改。
TLDR: 我通过 git rm -rf .
删除了我的整个项目,我需要一些方法来重置删除,以便我保留未提交的更改并取回我的文件.拜托,我太害怕我可能会失去我的整个项目。
答案:我的资料库基本上是一个有很多内容的网站,根据下面的回答,我制作了我的资料库的 2 个副本,我们称它们为副本 A 和副本B,对于 A,我做了 git reset --hard
返回到最新的提交,我拿回了我的文件,但丢失了我对它们所做的更改。所以对于副本 B,我做了 git fsck --lost-found
并进入了 .git/lost-found/other/ 目录,其中包含我文件的多个哈希命名版本,我一直打开它们中的每一个,它们超过 60文件 btw,我识别的每个文件我都将其重命名为它的实际名称,然后将它而不是旧版本放在副本 A 中,最后我删除了我的原始 repo,我现在使用副本 A 作为我的网站。现在好像什么都没有发生。一个小愚蠢的错误 => 5 小时的痛苦。不要重复我所做的,永远不要。
现在 git status
将我的所有文件显示为 "deleted: " 并且显示为绿色。
正如评论者所说,您应该做的第一件事是备份您的项目目录。
您可以使用 git reset --hard HEAD
取回您提交的文件。由于您清除了登台树,因此您未提交的更改不再在 git 中(正如其他几个答案所指出的,这可能不是真的)所以您恢复它们的唯一机会是您或您的任何备份 OS 可能做出来了。
很抱歉,这对眼前的情况没有帮助,但为了将来参考,您可以使用 git reset HEAD
取消暂存您的更改。
对于已经提交的文件,git reset --hard
会全部恢复。
对于已添加但未提交的,请尝试 git fsck --lost-found
。它将打印悬挂的斑点并在 .git/lost-found/other
中制作它们的副本。您可以 运行 git cat-file -p $blob
或 cat .git/lost-found/other/$blob
来查看内容。 blob不记录文件路径,所以需要通过内存映射内容和文件路径,或者通过git grep $keyword
没有新修改的关键字。找到 blob 的路径后,运行 cp .git/lost-found/other/$blob $path
恢复它。
正在使用
find .git/objects/ -type f -printf "%T+\t%p\n" \
| sort \
| sed 's:.*git/objects/\(.*\)/\(.*\)::' \
| 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
最后两个 blob 是在最后一次提交之后创建的,如果您使用 eg 打印它们。 git cat-file -p 40cda8e010466dc7a4a0eb107e7e45804290685e
,您应该能够恢复文件内容。
您也可以通过这种方式得到一些树(使用 git ls-tree <tree-id>
打印它们),但 top-level 不行,因为它直接存储在索引中。
可能还有希望:您之前添加到索引中的对象可能仍然存在,尽管它们不再被引用。我做了以下测试:
$ 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 fsck --lost-found
.
将它们全部转储到 .git/lost-found/other
索引本身没有存储为 Git 对象,而是直接驻留在 .git/index
中,所以我认为这已被不可逆转地覆盖。这意味着文件的路径以及任何元数据(例如权限)都已丢失。
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
git add *
、我对暂存索引添加了一堆更改,但尚未提交,我想删除它们,撤消添加 ,所以我做了 git rm -rf .
令我惊讶的是它从我的硬盘驱动器中删除了它们,我想要一种方法来恢复它们;但是,我已经进行了巨大的更改,我想恢复这些更改。
TLDR: 我通过 git rm -rf .
删除了我的整个项目,我需要一些方法来重置删除,以便我保留未提交的更改并取回我的文件.拜托,我太害怕我可能会失去我的整个项目。
答案:我的资料库基本上是一个有很多内容的网站,根据下面的回答,我制作了我的资料库的 2 个副本,我们称它们为副本 A 和副本B,对于 A,我做了 git reset --hard
返回到最新的提交,我拿回了我的文件,但丢失了我对它们所做的更改。所以对于副本 B,我做了 git fsck --lost-found
并进入了 .git/lost-found/other/ 目录,其中包含我文件的多个哈希命名版本,我一直打开它们中的每一个,它们超过 60文件 btw,我识别的每个文件我都将其重命名为它的实际名称,然后将它而不是旧版本放在副本 A 中,最后我删除了我的原始 repo,我现在使用副本 A 作为我的网站。现在好像什么都没有发生。一个小愚蠢的错误 => 5 小时的痛苦。不要重复我所做的,永远不要。
现在 git status
将我的所有文件显示为 "deleted: " 并且显示为绿色。
正如评论者所说,您应该做的第一件事是备份您的项目目录。
您可以使用 git reset --hard HEAD
取回您提交的文件。由于您清除了登台树,因此您未提交的更改不再在 git 中(正如其他几个答案所指出的,这可能不是真的)所以您恢复它们的唯一机会是您或您的任何备份 OS 可能做出来了。
很抱歉,这对眼前的情况没有帮助,但为了将来参考,您可以使用 git reset HEAD
取消暂存您的更改。
对于已经提交的文件,git reset --hard
会全部恢复。
对于已添加但未提交的,请尝试 git fsck --lost-found
。它将打印悬挂的斑点并在 .git/lost-found/other
中制作它们的副本。您可以 运行 git cat-file -p $blob
或 cat .git/lost-found/other/$blob
来查看内容。 blob不记录文件路径,所以需要通过内存映射内容和文件路径,或者通过git grep $keyword
没有新修改的关键字。找到 blob 的路径后,运行 cp .git/lost-found/other/$blob $path
恢复它。
正在使用
find .git/objects/ -type f -printf "%T+\t%p\n" \
| sort \
| sed 's:.*git/objects/\(.*\)/\(.*\)::' \
| 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
最后两个 blob 是在最后一次提交之后创建的,如果您使用 eg 打印它们。 git cat-file -p 40cda8e010466dc7a4a0eb107e7e45804290685e
,您应该能够恢复文件内容。
您也可以通过这种方式得到一些树(使用 git ls-tree <tree-id>
打印它们),但 top-level 不行,因为它直接存储在索引中。
可能还有希望:您之前添加到索引中的对象可能仍然存在,尽管它们不再被引用。我做了以下测试:
$ 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 fsck --lost-found
.
.git/lost-found/other
索引本身没有存储为 Git 对象,而是直接驻留在 .git/index
中,所以我认为这已被不可逆转地覆盖。这意味着文件的路径以及任何元数据(例如权限)都已丢失。
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