13

在合并我同事的捆绑包后,我观察到了 CRLF 问题。有时,带有 LF 的行会被混入源代码中,可能是那些被合并的行。因此,我们决定添加.gitattributes具有以下内容的文件(已删除注释):

*.cpp text
*.h text
*.inc text
*.cfg text
*.dic text

*.sln text eol=crlf
*.vcxproj text eol=crlf
*.filters text eol=crlf
*.user text eol=crlf
*.rc text eol=crlf
*.rc2 text eol=crlf

现在我观察到奇怪的行为。我可以看到很多modified: ...不应该存在的文件(即未暂存的)。我试过git reset --hard了,但文件仍然具有相同的状态。我试图再次克隆存储库——结果相同。

我已经git version 1.7.11.msysgit.0Git-1.7.11-preview20120620.exe下载的当前版本的 Windows 安装。

我还应该尝试什么?

谢谢,彼得

4

1 回答 1

15

原因

它是* text=auto导致.gitattributes此问题的原因。您可以删除它并从此过上幸福的生活,但是您的 repo 中可能有具有非 repo 默认行编码的文件,甚至具有几种不同行结束编码的文件(即 LF 和 CRLF,甚至 CR!)。

为什么会发生这种情况(详细信息)

当 git 按原样签出文件时,它将在 add/commit 上修改行尾。该文件实际上尚未修改,但 git 已经将其视为已修改,因为它将是,由于 repo 的设置。

不知何故,它与 git 一起工作有点奇怪。例如,git reset --hard有时有效,有时无效,可能取决于您的设置。或者,如果您进入.gitattributes并将扩展标记为二进制,则修改后的文件会神奇地消失:

*.ext binary

即使您删除了二进制标记,即使您git reset --hard再次执行此操作,效果仍然存在,因此它可能是 git 错误或 git 缓存问题。对文件执行git -rm然后执行git reset --hard恢复修改的标记。

如何修复它

我们在这里假设您希望保留您的* text=auto设置,以便 git 警告您现在和将来各种文本文件中的行尾不一致。如果是这样,请选择您的方法:

选项 0:暂时欺骗 git 将文件标记为已修改

  1. 编辑.gitattributes、注释* text=auto、保存
  2. git status(这一步需要 git 记录 .gitattributes 中的更改)
  3. git reset --hard(如果您做了任何更改,这将恢复* text=auto并取消您工作目录中的任何更改)。

这通常有效(除了在最顽固的情况下)。它还推迟了问题,该问题很可能会在稍后出现,因为行尾仍未标准化。

当您必须回退尚未规范化的先前提交时,此选项非常有用,例如在变基期间或其他一些 git 工作期间,您知道现有的后续提交将使行尾正常化,但 git 抱怨修改后的文件现在阻止您从继续。因此,当您需要 git 关闭并忽略确实没有针对您的特定上下文进行修改的已修改文件时,基本上使用此方法。

选项 1:简单的“最终用户”修复

如果您只有几个文件,请确保您的.gitattributescore.autocrlf设置为您喜欢的,然后只需制作一个git add/commit,您应该不会再看到此问题。如您的配置中所述,这些文件将转换为您想要的行尾并存储在您的存储库中。此提交将作为“整个文件已更改”存储在您的存储库中,因为每一行都会更改其行尾。对于较大或开源存储库中的一些文件,这很好。确保将该提交合并或挑选到您的所有分支中,因为该问题将存在于具有这些文件的所有分支中,直到您修复它为止。顺便说一句,这里是您可以使用选项 0 的地方。即,如果您切换到未修复的分支,并且它抱怨,请运行选项 0,然后进行修复(合并或挑选)。

重要提示:如果您要使用选项 1 的这条路线,请务必正确转换修改后的文件。git 可能不会像你期望的那样为你做这件事,所以在你提交之前自己做,即使用这个:将换行格式从 Mac 转换为 Windows git 可能会感到困惑的原因是我已经看到了具有所有三个 CR 的文件, LF 和 CRLF 行结束格式在其中。在提交之前,自己将它们核对成您喜欢的格式。

选项 2:高级机制“git 历史重写”修复:

如果您有更私密的仓库并且不怕重写历史记录,请查看以下内容: 由于 mac 行结尾,git 将整个文件视为一行 这将重写整个仓库并消除所有树、分支上的任何行结尾问题, 永远!确保包括所有可能需要规范化的潜在麻烦的文本文件扩展名,否则它们可能会在以后出现。

就我而言,我做了选项 2,因为我正在处理许多分支中的许多文件结尾问题。但是后来我出现了一些意外的扩展,我没有规范化,只是做了选项 1,因为我只错过了 5-6 个文件。

于 2014-02-28T15:19:12.427 回答