可能的原因1-线路末端标准化
可能发生这种情况的一种情况是,当没有适当配置行尾(1)的情况下将相关文件检入到存储库中时,导致存储库中的文件具有错误的行尾或混合的行尾。要进行确认,请确认git diff
仅显示了行尾的更改(默认情况下可能看不见这些更改,请尝试git diff | cat -v
将回车视为文字^M
字符)。
随后,可能有人添加.gitattributes
或修改了core.autocrlf
设置以标准化行尾(2)。基于.gitattributes
或全局配置,Git已将本地更改应用于您的工作副本,该更改将应用请求的行末尾标准化。不幸的是,由于某些原因git reset --hard
并不能撤消这些行规范化更改。
解
重新设置本地行尾的解决方法无法解决问题。每次git“看到”文件时,它将尝试重新应用规范化,从而导致相同的问题。
最好的选择是让git通过对仓库中的所有行尾进行标准化以匹配.gitattributes
,并提交这些更改,从而应用所需的标准化,并提交这些更改-请参阅尝试使用git filter-branch来修复行尾,但是没有运气。
如果您真的想尝试将更改手动还原到文件,那么最简单的解决方案似乎是擦除已修改的文件,然后告诉git恢复它们,尽管我注意到该解决方案似乎无法始终如一地工作时间(警告:如果修改后的文件除行尾以外,请勿运行此命令!):
git status --porcelain | grep "^ M" | cut -c4- | xargs rm
git checkout -- .
请注意,除非您确实在某个时候对存储库中的行结尾进行了标准化,否则您将继续遇到此问题。
可能的原因2-区分大小写
第二个可能的原因是Windows或Mac OS / X上不区分大小写。例如,假设存储库中存在以下路径:
/foo/bar
现在,Linux上的某个人将文件提交/foo/Bar
(可能是由于构建工具或创建该目录的某种东西)并推送。在Linux上,实际上这是两个单独的目录:
/foo/bar/fileA
/foo/Bar/fileA
在Windows或Mac fileA
上签出此仓库可能会导致修改后的内容无法重置,因为每次重置时,Windows上的git都会签出/foo/bar/fileA
,然后由于Windows不区分大小写,会覆盖fileA
with 的内容/foo/Bar/fileA
,从而导致它们被“修改”。
另一种情况可能是存储库中存在单个文件,当在不区分大小写的文件系统上签出该文件时,它们会重叠。例如:
/foo/bar/fileA
/foo/bar/filea
可能还有其他类似情况可能导致此类问题。
不区分大小写的文件系统上的git应该确实检测到这种情况并显示有用的警告消息,但目前没有((将来可能会改变-请参阅git.git邮件列表上的讨论和相关建议的补丁程序)。
解
解决方案是使git索引中的文件大小写与Windows文件系统上的大小写对齐。这可以在显示事物真实状态的Linux上完成,也可以在Windows中使用非常有用的开源实用程序Git-Unite来完成。Git-Unite会将必要的大小写更改应用于git索引,然后可以将其提交给存储库。
(1)这是最有可能使用Windows的人,没有任何.gitattributes
有问题的文件定义,并使用默认的全局设置的core.autocrlf
是false
(见(2))。
(2)http://adaptivepatchwork.com/2012/03/01/mind-the-end-of-your-line/
.
代表当前目录而不是根目录