恢复已暂存但未提交的文件?

3
我已在现有项目中初始化了git仓库,暂存了所有文件,然后在没有进行初始提交的情况下决定清理索引。我不确定为什么我认为这是个好主意,但我立即输入了git reset --hard(我无法真正说出当时我的想法,也许是因为几个不眠之夜的影响)。现在所有的文件都不见了...
是否有可能至少恢复部分文件?我看到.git/objects/中注册了一些对象。

“git reset” 可能是使用 git 丢失工作的唯一保证方式。它会对您的工作目录进行永久性更改。 - Vincent Ramdhanie
@Mureinik,我说的是数百个文件,你提到的可能只适用于单个文件或最多几个文件的解决方案。 - jayarjo
@Vincent Ramdhanie,那些.git/objects/文件是什么(有很多,几乎44mb),它们保存了什么? - jayarjo
1个回答

3
如果在执行git reset之前使用git add将文件加入暂存区,则所有文件和描述目录层次结构的树对象都在您的对象数据库.git/objects中,除非已经过了足够长的时间进行垃圾回收,或者您自己运行了像git gc这样的命令。然而,重建这些东西需要一些工作 - git没有预先打包此功能。以下是一些提示:
  1. 对数据库中的每个对象使用git cat-file -t HASH以识别每个对象的类型。查找树对象。请注意,对象哈希被拆分以命名.git/objects中的文件。因此,具有哈希“db6689df4f8aae84d35df2e496158b2746bb0f1e”的对象实际上存储在.git/objects/db/6689df4f8aae84d35df2e496158b2746bb0f1e中,其中前两个字符用作子目录 - 您可以轻松地考虑这一点来重建对象哈希。如果您在.git/objects/pack中有文件,则可能需要额外运行git verify-pack -v .git/objects/pack/pack-HASH.pack以获取每个包文件中包含的对象列表。
  2. 对于每个树对象,请使用git cat-file -p HASH查找文件的原始文件名和哈希值(也称为“blob”)。其中一个树将与您的工作目录的根目录相匹配。一旦确定了根树对象,您可以
  3. 运行git ls-tree -r HASH以获取所有文件名及其各自的哈希值的完整列表。
  4. 对于要从上面的列表中恢复的每个文件,可以运行git show HASH > FILENAME来重新创建该文件 - 您需要手动创建子目录。

有了这些信息,编写一个执行繁重工作的脚本就不应该太难了。祝好运!

编辑:或者,一旦确定了根树对象,您只需echo "commit for recovery" | git commit-tree HASH,这将创建一个提交并向您报告该新提交的哈希。然后,您可以git checkout HASH以在工作目录中获取文件,并git branch BRANCHNAME以创建指向该提交的分支。如果您的git版本足够旧,则还可以查看git tar-treegit archive


没有找到树对象,只有 blob 对象... 最终我编写了一个脚本来遍历所有文件,识别 PHP 或 JS 文件(它们在头部具有特定的特征和命名空间),并从中重建目录结构和名称。成功恢复了大部分所需文件。无论如何,Git 是一个伟大的工具,你得到了一个很好的答案! - jayarjo
2
我猜如果你只是执行了 git add <file> ...,并且这些文件都不在子目录中,那么你可能没有任何树对象。另一方面,也有可能直到你执行 git commit 之前树才被创建,而信息只是存储在索引中(你已经重置了索引)... - twalberg
如果你是那些不幸陷入这种困境的少数人之一,这将是救命稻草。 - ijoseph

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接