2016-12-04 81 views
4

每次我犯了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冲突期间删除了它们,因为它们不再需要在此项目中(但之前已修改并已提交,因此存在冲突)。

这些文件是既不在指数也不在worktree发现:

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

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

+0

rerere记录位于'.git/MERGE_RR'中。不过,该文件应该在您中止或完成合并时清理完毕。 – torek

+0

@torek:该文件包含3条记录,仅通过'git rerere clean'删除。检查下面接受的答案(最近大大扩展)以获得确切的复制。不过,我目前在步骤41中感到困惑。 :) – kkm

回答

3

错误的来源是git的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. 创建一个名为再见文件的文件。RB用下面的代码

    #! /usr/bin/env ruby 
    
    def bye 
        puts "goodbye world" 
    end 
    
  10. $ git commit -m"added goodbye.rb"
  11. $ git branch i18-world
  12. 变化招呼HOLA在hello.rb的
  13. $ git commit -a -m"changed hello to hola in hello.rb"
  14. $ git checkout i18-world
  15. 变化的世界中hello.rb的蒙多
  16. $ git commit -a -m"changed world to mundo in hello.rb"
  17. 更改告别阿迪奥斯在goodbye.rb
  18. $ git commit -a -m"changed goodbye to adios in goodbye.rb"
  19. $ git checkout master
  20. 变化的世界中goodbye.rb蒙多
  21. $ git commit -a -m"changed world to mundo in goodbye.rb" 现在我们有两个分支,其中两个文件类似,但不完全相同。花一点时间查看每个文件,因为它存在于两个分支中。
  22. $ git status应该说

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

    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. 
    
  25. 你是不是在冲突状态,rerere正在尽工作......请注意上面记录的原像
  26. $ git rerere status回报goodbye.rb和hello.rb的,因为这两个文件都被记录了这次冲突。不适合尝试git rerere diffgit ls-files -u现在,让我们创建一个错误状态。
  27. 首先,让我们解决hello.rb的打印hola mundo,并且没有提交,让$ git rm goodbye.rb这会导致你的错误。看看$ git status看到确实goodbye.rb已被删除(尽管git抱怨)和hello.rb已被修改并准备合并。
  28. $ git commit -a -m"HUH?"
  29. 注意,你在这一点上的错误是完全一样的问题描述的错误,而且我们也有一个巨大的线索,发生了什么事时录制的原像位显示出来。现在让我们确定它真的被破坏了。
  30. $ git log --oneline --decorate --graph --all看到我们的提交历史的美丽图片。
  31. 将hello.rb从'hola mundo'更改为'hola chica bonita!'
  32. $ git commit -a -m"changed 'hola mundo' to 'hola chica bonita!' in hello.rb"
  33. 注意,错误仍然显示了,我们仍然得到录制的原像
  34. $ git rerere status还是应该回到goodbye.rb,因为它仍然记录在原像。
  35. $ git rerere diff因为goodbye.rb不存在返回致命错误。
  36. 对于一个清晰的画面,$ git log --oneline --decorate --graph --all
  37. 同样请注意,git statusgit rerere status不会回到这个悬而未决的状态是一样的。验证你自己的理智,goodbye.rb不存在于你的工作目录中。
  38. 现在,让我们通过固定检查出的承诺,我们只是我们合并之前的那个讨厌的错误消息。如果你一直关注你的提交信息,那就是说“改变再见,再见了。”。我们将用$ git checkout **yoursha1** goodbye.rb来使用特定于文件的签出(因为我们不想搞乱hello.rb中的工作)。
  39. 验证hello.rb没有被更改。应该说'hola chica bonita!'。
  40. 大FIX!git rerere ...达达! 注意 git说记录的'goodbye.rb'的决议。
  41. 好的,如果你不困惑,布拉沃!起初我对此非常困惑,但后来我记得...... rerere只是想重新使用我已经应用的决议。唯一的抱怨是我从文件下面删除了一个文件,没有给它一个追上的机会。现在再见了再见,它很乐意删除它所带来的参考,并且生活在一个不再存在再见的世界里。神奇的是,没有更多的错误。
  42. 好吧,我会证明给你,因为你仍然怀疑。
  43. $ git checkout i18-world
  44. $ git rebase master
  45. $ git status回报nothing to commit, working tree clean
  46. $ ls返回 “hello.rb的”,所以我们知道我们正在摆脱那个讨厌的goodbye.rb文件。
  47. $ git log --oneline --decorate --graph --all向我们展示了我们所有的辛勤工作。
  48. $ git rerere status不会返回任何内容,因为没有任何内容被跟踪(无前导图)。
  49. $ cat hello.rb向我们展示了从

    #! /usr/bin/env ruby 
    
    def hello 
        puts 'hola chica bonita!' 
    end 
    
  50. 变化hello.rb的 'HOLA奇卡博尼塔!'到'hola chica bonita! te amo'。
  51. $ git commit -a -m"updated hello in hello.rb to say 'hola chica bonita! te amo"
  52. git log --oneline --decorate --graph --all看到I18世界领先高手。
  53. $ git checkout master
  54. $ git merge i18-world
  55. $ git branch应该返回i18-world *master
  56. $ git branch -d i18-world

现在,您大可放心,你的工作目录是干净的,没有错误。此外,如果您需要回到'goodbye.rb'存在的状态,您可以!

我对此答案的长度表示歉意,但希望现在您明白事情出错的地方,以及如何轻松(至少在这个微小的示例中)可以修复它们。

+0

谢谢,'git rerere明确'做到了!我可以请求扩大你的答案吗?就我的搜索能力来说,这种情况在SO上没有被涵盖。虽然我得到了指示并且投了(可能)正确的咒语,但我还是不完全理解发生了什么。 – kkm

+0

对不起,延迟响应,我花了一些时间来重新创建您的错误代码。如果你花时间跟随我的榜样,我相信你会明白发生了什么事以及将来如何预防它。当你使用'git rerere clear'时,你很可能会抛弃所有的解析记录,如果你遇到类似的情况,这可能不是你将来寻找的东西。 〜谢谢你的一个很好的问题,我学会了分配! – quarterpi

+0

令人惊叹的,谢谢! – kkm