git commit错误消息:无法打开(以前删除的源文件)

时间:2016-12-04 05:17:23

标签: git

每次我在git存储库中提交任何内容时,我都会收到一条(显然无害的)错误消息,提示一些不再存在的文件:

$ git commit -a
error: Could not open cssrc/csgrpc/Main.cs
error: Could not open cssrc/csgrpc/Main.cs
Recorded preimage for 'cssrc/csgrpc/Main.cs'
... more 3-line groups like one above ...
[x017-upgrade a86861b] Point Audio to new location of....
 1 file changed, 1 insertion(+), 1 deletion(-)

这些文件最初是子树的一部分,由git subtree -P cssrc ...维护,我在git subtree pull冲突期间删除了它们,因为这个项目不再需要它们(但之前已经修改过并且已经提交了)因此是一场冲突。)

文件确实既没有在索引中也没在工作树中找到:

$ git ls-files -cs | grep Main.cs
$ find -name 'Main.cs'
$

rerere.enabled选项设置为true。这是罪魁祸首吗?指向这些文件名的卡住指针存储在哪里?如何清洁?

1 个答案:

答案 0 :(得分:3)

错误来源是git' s rerere或“重复记录的分辨率”功能。由于您在git subtree pull conflict"期间删除了它们(您的文件),因此您无意中将git置于"未解决的"州。 git rerere尽力保持清晰的冲突解决记录,以便以后再使用。因为您在冲突解决过程中删除了文件,所以您在rerere中引用了这些文件,导致git查找不再存在的文件。了解为了让git重用已记录的分辨率,它必须记录所涉及的步骤。但是,这并不意味着git正在跟踪您使用的命令;这解释了为什么它不知道为什么处于冲突状态的文件在其解析状态中缺失。它希望您选择该文件的一个版本或另一个版本,而不是完全删除文件。

如果您有兴趣详细了解git rerere,建议您阅读git manual pages

如果您对此问题中描述的问题的工作示例感兴趣,并且对此问题有解决方案(我确定还有更多问题),请按照下面列出的步骤操作。我知道这很长,但我不知道如何澄清这个问题。

在适合测试代码的目录中......

  1. $ mkdir test_rerere
  2. $ cd test_rerere
  3. $ git init
  4. $ cd .git
  5. $ mkdir rr-cache
  6. $ cd ..
  7. 使用以下代码

    创建名为hello.rb的文件
    #! /usr/bin/env ruby
    
    def hello
      puts 'hello world'
    end
    
  8. $ git commit -a -m"added hello.rb"
  9. 使用以下代码

    创建名为goodbye.rb的文件
    #! /usr/bin/env ruby
    
    def bye
      puts "goodbye world"
    end
    
  10. $ git commit -m"added goodbye.rb"
  11. $ git branch i18-world
  12. 在hello.rb
  13. 中将hello更改为hola
  14. $ git commit -a -m"changed hello to hola in hello.rb"
  15. $ git checkout i18-world
  16. 在hello.rb中将世界更改为mundo
  17. $ git commit -a -m"changed world to mundo in hello.rb"
  18. 在goodbye.rb中告别adios再见。
  19. $ git commit -a -m"changed goodbye to adios in goodbye.rb"
  20. $ git checkout master
  21. 在goodbye.rb中将世界改为mundo
  22. $ git commit -a -m"changed world to mundo in goodbye.rb" 现在我们有两个分支,两个文件相似,但不完全相同。花一点时间查看两个分支中存在的每个文件。
  23. $ git status应该说

    On branch master
    nothing to commit, working tree clean
    
  24. $ git merge i18-world
  25. 你应该得到这样的东西......

    Auto-merging hello.rb
    CONFLICT (content): Merge conflict in hello.rb
    Auto-merging goodbye.rb
    CONFLICT (content): Merge conflict in goodbye.rb
    Recorded preimage for 'goodbye.rb'
    Recorded preimage for 'hello.rb'
    Automatic merge failed; fix conflicts and then commit the result.
    
  26. 你没有处于冲突状态,而rerere正在做它的工作......注意上面的记录的原像日志。
  27. $ git rerere status返回goodbye.rb和hello.rb,因为这两个文件都是为此冲突而记录的。不是试用git rerere diffgit ls-files -u的好时机。现在,让我们创建一个错误状态。
  28. 首先,让我们解析hello.rb以打印hola mundo,并且不提交,允许$ git rm goodbye.rb这会导致您的错误。看看$ git status,看看确实已经删除了goodbye.rb(虽然git抱怨)和hello.rb已被修改并准备合并。
  29. $ git commit -a -m"HUH?"
  30. 请注意,此时出现的错误与问题中描述的错误完全相同,并且我们还有一个巨大的线索,说明当录制的preimage 位出现时发生了什么。现在让我们确保它真的坏了。
  31. $ git log --oneline --decorate --graph --all可以看到我们提交历史的精彩图片。
  32. 从&hola mundo'更改hello.rb来自' hola chica bonita!'
  33. $ git commit -a -m"changed 'hola mundo' to 'hola chica bonita!' in hello.rb"
  34. 请注意,错误仍然显示,我们仍然会收到录制的原像
  35. $ git rerere status仍然应该返回goodbye.rb,因为它仍然记录在原像中。
  36. $ git rerere diff返回致命错误,因为goodbye.rb不存在。
  37. 要获得清晰的图片$ git log --oneline --decorate --graph --all
  38. 再次注意,git statusgit rerere status在此未解决状态下不会返回相同的内容。验证您的工作目录中不存在goodbye.rb的完整性。
  39. 现在,让我们通过检查我们在合并之前做出的提交来修复那个讨厌的错误消息。如果你一直关注你的提交信息,那就是那个说再见的人告别了adby.rb"。我们将使用$ git checkout **yoursha1** goodbye.rb使用特定于文件的结帐(因为我们不想在hello.rb中搞乱我们的工作)。
  40. 确认hello.rb未被更改。应该说' hola chica bonita!'。
  41. BIG FIX! git rerere ... Ta Da! 注意 git说记录了' goodbye.rb'
  42. 的解决方案
  43. 好的,如果你不感到困惑,布拉沃!起初这对我来说非常混乱,但后来我记得...... rerere只是想要重用我已经应用过的分辨率。它唯一的抱怨是我从它下面删除了一个文件而没有给它机会赶上来。现在再次存在goodbye.rb,它非常乐意删除它所携带的引用,并生活在一个不再存在goodbye.rb的世界中。神奇的是,没有更多的错误。
  44. 好的,我会向你证明这一点,因为你仍然持怀疑态度。
  45. $ git checkout i18-world
  46. $ git rebase master
  47. $ git status返回nothing to commit, working tree clean
  48. $ ls返回" hello.rb"所以我们知道我们摆脱了那个讨厌的goodbye.rb文件。
  49. $ git log --oneline --decorate --graph --all向我们展示了我们所有的辛勤工作。
  50. $ git rerere status不返回任何内容,因为没有任何内容被跟踪(没有预先映像)。
  51. $ cat hello.rb告诉我们

    #! /usr/bin/env ruby
    
    def hello
      puts 'hola chica bonita!'
    end
    
  52. 从&#ch; chica bonita改变hello.rb!'来自&hola chica bonita! te amo'。
  53. $ git commit -a -m"updated hello in hello.rb to say 'hola chica bonita! te amo"
  54. git log --oneline --decorate --graph --all看到i18世界领先于大师。
  55. $ git checkout master
  56. $ git merge i18-world
  57. $ git branch应该返回i18-world *master
  58. $ git branch -d i18-world
  59. 您现在可以确信您的工作目录是干净且无错误的。此外,如果你需要回到“再见”的状态,那就是'存在,你可以!

    我为这个答案的长度道歉,但希望现在你能够理解出错的地方,以及解决问题的方法(至少在这个小例子中)是多么容易。