在添加.gitattribute文件后使用git reset --hard命令出现问题——本地应该不存在的更改。

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.0,是从Windows的当前版本中下载的Git-1.7.11-preview20120620.exe

我应该尝试什么其他方法?

谢谢, Petr


1
也许这里有解决方案:https://dev59.com/GGgu5IYBdhLWcg3wWl4q? - Martin Tajur
谢谢,马丁。可能会相似。我已经放弃并删除了.gitattribute。它做了一些奇怪的事情。它可能已经在以后的版本中修复了,但是1.7.11.msysgit.0是当时最新的可用版本。 - pepr
我在这里也遇到了很多.gitattributes的问题,考虑摆脱它。 - Martin Tajur
1个回答

15

原因

这个问题是由于在 .gitattributes 中的 * text=auto 设置导致的。你可以将其删除并快乐地生活下去,但是你的存储库中可能有具有非默认行编码的文件,甚至有多种不同的行结尾编码(即LF和CRLF,甚至CR!)。

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

当 git 按原样检出文件时,在添加/提交时它将修改行结尾。实际上,文件还没有被修改,但是由于存储库的设置,git 已经将其视为已修改。

有些时候 git 的工作方式有点奇怪。例如,git reset --hard 有时可以正常工作,有时不能,可能取决于你的设置。或者,如果你进入你的 .gitattributes 并将扩展名标记为二进制,那么这个修改过的文件就会神奇地消失:

*.ext binary

该效果甚至在您删除二进制标记后仍然存在,甚至在您再次执行git reset --hard之后也是如此,因此这可能是一个git bug或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并清除您的工作目录中的任何更改,如果有的话)。
这通常有效(除了可能最顽固的情况)。它也会推迟问题,因为行尾仍未被规范化,最有可能在以后某个时刻出现。
当您必须回滚一个尚未规范化的先前提交(例如在 rebase 或其他 git 工作期间),或者您知道现有的后续提交将规范化行尾但 git 抱怨修改的文件现在阻止您继续进行时,此选项非常有用。因此,当您需要 Git 保持安静并忽略真正未针对特定上下文修改的修改文件时,请使用此方法。
选项1:易于“最终用户”解决方案。
如果你只有几个文件,确保你的 .gitattributescore.autocrlf 设置为你喜欢的方式,然后只需进行 git add/commit 即可,你就不会再看到这个问题了。这些文件将被转换为你想要的行结尾并存储在你的仓库中,正如你的配置所述。这个提交将被存储在你的仓库中,因为每一行都会改变它的行结尾,所以会被记录为“整个文件已更改”。对于一个较大或开源的仓库中的几个文件来说,这是可以接受的。确保将该提交合并或 cherry-pick 到你的所有分支中,因为在拥有这些文件的所有分支中,这个问题都会存在,直到你解决它。顺便说一下,在这里你可以使用选项 0。也就是说,如果你切换到一个未修复的分支,并且它抱怨,运行选项 0,然后进行修复(合并或 cherry-pick)。
重要提示:如果您选择选项1,请确保正确转换已修改的文件。 Git 可能无法像您期望的那样为您执行此操作,因此在提交之前自己进行转换,即使用此方法:将 Mac 格式的换行符转换为 Windows 格式。Git 可能会混淆的原因是我见过一些文件中同时包含 CR、LF 和 CRLF 行结束格式。在提交之前请自己将其转换为所需的格式。
选项2:高级机制“git 历史重写”修复:
如果您拥有更私密的存储库并且不怕重写历史,请参考以下内容:由于 Mac 换行符,Git 将整个文件视为一行。这将重写整个存储库,并消除所有树、分支上的任何行结束问题!请确保包括所有可能引起问题的文本文件扩展名,否则它们可能会在以后出现。
在我的情况下,我选择了方案2,因为我需要处理许多分支中的很多文件结尾问题。但是后来我发现了一些意外的扩展名没有被规范化,所以我只好使用了方案1,因为我只错过了5-6个文件。

2
感谢您详细的回答。 - pepr

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接