【问题标题】:Recover once staged but not committed files?恢复一次暂存但未提交的文件?
【发布时间】:2015-07-11 09:07:36
【问题描述】:

我已经在现有项目中初始化了 git repo,暂存了所有文件,然后在不进行初始提交的情况下决定清理索引。不知道为什么我认为这是一个好主意,但我立即输入了git reset --hard(我现在无法真正说出我的想法,也许几个不眠之夜造成了损失)。现在所有文件都不见了...

是否有可能至少恢复一些?我看到有.git/objects/注册的对象。

【问题讨论】:

  • git reset 可能是唯一能保证让你失去 git 工作的方法。它会永久更改您的工作目录。
  • @Mureinik,我说的是数百个文件,您所引用的可能是单个文件的解决方案,也可能是最多几个文件。
  • @Vincent Ramdhanie,那么 .git/objects/ 文件是什么(很多,差不多 44mb),它们有什么?

标签: git


【解决方案1】:

如果您在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 tar-tree,如果你的git版本够老,或者git archive

【讨论】:

  • 还没有找到树对象,只有 blob...我最终得到了遍历所有文件的脚本,识别 php 或 js(在标头中都有特定的特征和命名空间)文件并在那里重建目录结构和名称。能够恢复大部分所需文件。无论如何,git 是一个很棒的工具,你得到了一个很好的答案!
  • 我想如果你刚刚做了git add <file> ...,并且这些文件都不在子目录中,那么你可能没有任何树对象。再说一次,在你执行git commit 之前,树可能不会被创建,并且信息只是存储在索引中(你已经重置)直到那时......
  • 如果您碰巧是少数几个设法让自己陷入这种困境的可怜人之一,那么您可以救命。
猜你喜欢
  • 2018-01-11
  • 2021-03-26
  • 2016-06-25
  • 2021-03-12
  • 2019-05-06
  • 2018-10-04
  • 1970-01-01
  • 2020-11-04
  • 1970-01-01
相关资源
最近更新 更多