我一般不太熟悉 git 恢复,但您可能想看看这个 stackoverflow 问题:
Accidentally reverted to master, lost uncommitted changes
假设您没有对git add、git stash 和git commit 进行更改。所以我认为上述问题的已接受答案中概述的方法都不起作用。
根据您所说,执行git fsck --lost-found 后,您的文件现在位于.git\lost-found\other 文件夹中,您可以使用git show <SHA1> 查看blob。 git rebase 仅适用于 commits 而不是 blob,这就是它不起作用的原因。
我认为最安全的方法是编写脚本或手动为每个 blob 执行 git show 并将输出通过管道传输到文件。假设有一个名为4156fb7a 的blob,它最初是您存储库中的README.txt 文件。你会这样做:
git show 4156fb7a > README.txt
因此,该 blob 的内容现在可以输出到 README.txt。如果您手动执行此过程会很乏味,但这可能是一种安全的方式。
我认为.git\lost-found\other 文件夹中不存在的任何内容都可以假定为永远丢失。记得尽早并经常提交。希望对您有所帮助。
编辑以更新答案:
@Malaka,如果没有很多 blob,您可以自己检查它们。否则,这只是一个猜测,但我猜你可能没有修改所有 900 个文件。如果你记得你修改了什么,那么恢复工作就容易多了。否则,你可能想看看我下面的建议。
我要建议的是可能会或可能不会成功的东西。它假设存在原始文件的另一个文件夹,无论该文件夹是 git repo 还是其他。如果您没有其他原始文件夹/存储库,那么我下面的想法是无用的。
第 1 步:
编写一个计算机程序,对原始文件夹中的每个文件应用一些校验和,例如 SHA1(使用sha1sum 实用程序;如果不存在,请使用md5sum)。该计算机程序最终会生成一个具有以下格式的文本文件:
fullFileName<SP>SHA1 checksum
<SP> 代表空格。因此,假设我在原始文件夹/repo 中有以下文件:
app/controllers/ApplicationController.rb
assets/utilities.js
README.markdown
然后您的程序将生成一个如下所示的文件。校验和当然都是组成的:
app/controllers/ApplicationController.rb 01dfea13
assets/utilities.js 55a31aae
README.markdown 9671c6a0
从现在开始,我们将上述文件称为checksumfile。
我希望您的原始文件不要使用空格。如果有,只需使用其他分隔符来分隔文件名及其校验和。
第 2 步:
现在,编写另一个计算机程序(我们称之为blobCat),将git show 应用于.git\lost-found\other 文件夹中的每个blob,并将它们输出到另一个文件夹中的任意命名文件。我们将用unknownBlobs 表示该文件夹。为简单起见,您可以将它们输出为0.txt、1.txt、2.txt 等等,换句话说,只需使用一些整数计数器来命名它们。
完成后,编写另一个读取checksumfile 的程序,并使用字典将校验和索引到原始文件名。换句话说,给定上面的checksumfile,我们将生成以下字典/哈希:
"01dfea13" => "app/controllers/ApplicationController.rb" 01dfea13
"55a31aae" => "assets/utilities.js"
"9671c6a0" => "README.markdown"
现在,遍历由blobCat 程序生成的unknownBlobs 文件夹(包含所有0.txt、1.txt、2.txt 文件的文件夹),并应用与第一个相同的校验和实用程序生成checksumfile 时的步骤。如果您在字典中找到校验和,这意味着该 blob 非常可能是该文件的原始文件,您可以安全地将其还原到另一个文件夹中的层次结构。您可能需要检查是否存在具有相同校验和的另一个 blob,以防发生校验和冲突,尽管这不太可能发生。
对于在字典中找不到校验和的 unknownBlobs 文件夹中的任何 blob,这可能意味着以下任何一种:
- 它是根据原始存储库中存在的某些文件修改的
- 它不是存储库的一部分
- 这是一个新创建的文件,从未被跟踪过
在任何情况下,只需跟踪那些在字典中找不到的 blob,并在所有内容的末尾输出它们的名称。这应该是一组相当小的 blob,因此您可以手动检查它们并确定它们是否是原始存储库的一部分,然后将它们复制到它们的目标位置。
上面的内容听起来很乏味,但我认为这比尝试自己检查所有 blob(假设有很多 blob)要快得多。