代码之家  ›  专栏  ›  技术社区  ›  ivan_pozdeev RenanSS

如何在更改core.autocrlf后强制转换工作树文件?

  •  0
  • ivan_pozdeev RenanSS  · 技术社区  · 6 年前

    我在Windows上,拥有全系统 core.autocrlf=true .

    对于特定的存储库,我在本地将其覆盖为 false .

    • 如果我手动转换文件,例如。 dos2unix ,它们显示为已更改。
    • git checkout --force HEAD ,没有效果。

    我找到的唯一有效方法是删除所有文件,然后 git reset --hard 这是相当尴尬的(=没有简单可靠的命令来做这件事,而且它做了很多不必要的工作--一切都是从头开始重新创建的,而不仅仅是覆盖需要转换的文件)。

    1 回复  |  直到 6 年前
        1
  •  7
  •   torek    5 年前

    TL;博士

    这是三种可能的解决方案(不一定是 只有 三)。

    1. 使用:

      git add --renormalize .
      

      注意:我根本不清楚这是否会影响 工作树 git checkout -- .

    2. 对于每个 git status rm file ; git checkout -- file . 这个 rm 删除工作树副本,以便 git checkout 必须根据新行结束规则重新提取文件。

      git rm -r .; git checkout HEAD -- . (只有两个命令)但这会产生一个副作用,即触摸工作树中的所有文件,甚至是任何不需要更改的文件(其中没有回车符的文件)。

    3. dos2unix 像你一样,快跑吧 git add . ).尽管表面上看,这应该保持指数不变。

    在所有情况下,之后, git状态 应该说 nothing to commit, working tree clean

    长的

    这不是 相当地 Git: how to renormalize line endings in all files in all revisions? ,因为您不想重新复制一组现有提交。但是, git add --renormalize 答案应该是可行的。

    PetSerAl's comment answer .

    或者,如果这失败了,或者您的Git太旧,无法使用 --renormalize 选项:

    如果我手动转换文件,例如。 dos2unix

    您可以手动转换文件,然后 git add . ,或删除工作树副本和 git checkout --force HEAD 失败是因为Git太聪明了,不利于自身:它(错误地)看到工作树副本已经正确,并避免对其进行操作。

    在任何时候都有,, README.txt prog.cc ,它们在工作树中都有CRLF结尾,但在存储库中只有LF行结尾。

       HEAD          index       work-tree
    ----------    ----------    ----------
    README.txt    README.txt    README.txt
    prog.cc       prog.cc       prog.cc
    

    副本在 指数 是可写的,但最初与提交中的副本匹配。因此,它也将有LF-only行结尾。它也是压缩的(最初它实际上只是对提交副本的引用)。

    工作树 .gitattributes 文件(无)和您的 core.autocrlf core.eol 等等你 它们设置为将LF更改为CRLF,因此工作树中的副本此时具有CRLF结尾。

    现在 之后 改变 您的设置,以便签出的文件将只有LF行结尾,或保留索引中的内容。不幸的是,文件的每个索引副本中都有一个条目是信息 工作树副本。这使得Git 假定

    git状态 必修的 换言之,它必须做出这样的假设。

    如果您没有更改下线设置, 我什么也不说,这不会打扰任何人,因为如果你跑 就说,, 自述文件 HEAD 复制,以及 git状态

    但是你 更改下线设置,以便 git添加 现在,Git应该将CRLF结尾复制到索引中。基本上, 已经被愚弄了:指数说的是目的!工作树副本匹配(即使不匹配),并运行

    如果你使用 在要更改工作树副本的文件上,Git现在看到工作树副本的统计信息与索引保存的“此文件是干净的”统计信息不匹配。就是, git状态 他仍然被愚弄 git添加 现在 ,Git将在更新索引副本时保留仅LF行的结尾。最终结果将是索引副本与 毕竟是抄袭,, Git会更新缓存的工作树统计信息 关于 文件,以便知道索引副本与工作树副本匹配。

    本质上,在更改行结束设置后 .gittributes 和/或 core.* 唯一的方法是强制Git从索引复制到工作树:

    rm worktreefile
    git checkout -- worktreefile
    

    或强制Git从工作树复制到索引:

    git add worktreefile
    

    这两种方法都修复了索引的缓存数据,但显然在这个过程中会带来一些额外的暴力。

    请注意,如果 复制有CRLF结尾,事情变了

    假设提交的 自述文件

    • 索引副本与
    • 如果工作树中有CRLF结尾,则所有三个副本都匹配;
    • 但是,如果您在工作树中选择了LF only endings,并实现了这一点,则工作树副本与两者都不同 和索引。

    git状态 他被愚弄了。

    一旦将工作树的LF only行结尾复制到索引中,使索引也具有LF only行结尾, 现在 索引副本(“为提交而暂存”)与 复制在这一点上,如果你 新的