这一行结束问题让我疯狂......
背景:从历史上看,我使用的是core.autocrlf设置,但我发现我遇到了不同的repos表现不好的问题(我在Windows上工作,我有一些需要LF结尾的repos和一些需要CRLF结尾的repos).所以我试图摆脱它并在每个存储库中使用.gitattributes(我希望Git只是闭嘴并让我管理行结尾!).所以,我现在有core.autocrlf=false和一个.gitattributes看起来像这样对我工作的一个Visual Studio项目:
# Don't do any end of line normalization.
* -text
# Always treat these files as binary. Not strictly necessary, but can't hurt.
*.png binary
*.gif binary
*.jpg binary
*.jpeg binary
*.dll binary
*.doc binary
*.docx binary
*.xls binary
*.xlsx binary
*.pdf binary
Run Code Online (Sandbox Code Playgroud)
我已经使用unix2dos将repo中的所有文件强制为CRLF结尾并确认它们在工作目录中具有正确的行结尾,并将它们全部检入.是的我遵循了这里的建议尝试使用git过滤器修复行结尾 - 分手,但没有运气
这几乎是完美的.
问题是每当我更改文件时,git报告它在更改的行上有行结束差异,例如,如果原始行是
string s;
Run Code Online (Sandbox Code Playgroud)
并且更改的行是
string sucks;
Run Code Online (Sandbox Code Playgroud)
git diff将更改显示为
string sucks;^M
Run Code Online (Sandbox Code Playgroud)
看起来Git认为repo中的文件仍然有LF结尾(因为它们在过去被标准化了?).^ M会产生大量的视觉噪音,我不确定这是否是其他任何问题的症状.我不明白为什么Git会报告差异,因为我在之前的提交中检查了所有带有CRLF结尾的文件,实际上是在此之前的提交.
那么为什么我会得到这些"假的"差异,我怎么能摆脱它们呢?
哇噢!我想我找到了答案.本网站http://lostechies.com/keithdahlby/2011/04/06/windows-git-tip-hide-carriage-return-in-diff/建议做
git config [--global] core.whitespace cr-at-eol
Run Code Online (Sandbox Code Playgroud)
这确实关闭了"git diff".当然,最好的解决方案是在.gitattributes文件中执行等效操作,以使其与repo保持一致,并且不依赖于用户的设置.
.gitattributes的确定设置
花了一些时间在Linux和Windows上尝试使用repos,以及使用具有Unix和Windows行结尾的文件,我相信如果你只是给你的git repo一个.gitattributes文件,整个行尾问题就可以消失了.两行:
* -text
* whitespace=cr-at-eol
Run Code Online (Sandbox Code Playgroud)
第一行阻止git执行任何行结束规范化,第二行停止git-diff突出显示行末尾的CR字符.我能找到的唯一不足之处是如果你将一个文件从DOS转换为Unix,反之亦然:git-diff会将文件显示为已更改,但它没有突出显示原因,而只是显示每一行删除然后添加.我可以忍受这个,因为它是一种罕见的操作(或应该是).
以上将行结束管理的负担放在提交者身上.这应该是,我不相信我的VCS工具应该试图做魔术,成千上万的网页和关于git处理行结尾的问题证明他们在这里作出了错误的决定.
变化
如果你用第一行替换
* eol=lf
Run Code Online (Sandbox Code Playgroud)
然后文件将始终在工作目录中有LF结尾.这对于必须在Unix和Windows上运行的存储库(例如".dotfiles")来说非常方便.同样eol=crlf会强制Windows样式行结尾.警告这也将转换二进制文件中的CRLF!请参阅我关于如何配置git repo的评论,以便所有文件都以行尾LF(而不是CFLF)存储?所以你还需要使用文件路径或告诉git哪些文件是二进制的.https://help.github.com/articles/dealing-with-line-endings/
方便的别名
以下两个git别名提供了一种快速方法,可以将repo中的所有文本文件从DOS转换为Unix,反之亦然.它们专门排除.git文件夹的任何处理.我找不到从命令行定义它们的方法,因此编辑.gitconfig并在该[alias]部分中添加以下两行:
godos = !find . -path ./.git -prune -o -type f -exec unix2dos {} "\\;"
gounix = !find . -path ./.git -prune -o -type f -exec dos2unix {} "\\;"
Run Code Online (Sandbox Code Playgroud)
然后,您可以执行git godos或git gounix在repo的根目录中将所有文本文件结尾设置为一个或另一个.nb以上仅适用于当前分支中的文件.我还没有找到一种方法来转换每个分支中的每个文件.
参考
gitattributes手册页:https://www.kernel.org/pub/software/scm/git/docs/gitattributes.html
gitconfig手册页(讨论cr-at-eol):https://www.kernel.org/pub/software/scm/git/docs/git-config.html
用于查找的Git别名:git别名中的`find -exec`