标准化后的Git行结束

时间:2014-07-04 15:42:31

标签: git

这一行结尾问题让我疯狂......

背景:从历史上看,我使用的是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

我已经使用unix2dos将repo中的所有文件强制为CRLF结尾,并确认它们在工作目录中具有正确的行结尾,并将它们全部检入。是的,我按照此处的建议Trying to fix line-endings with git filter-branch, but having no luck < / p>

这几乎是完美的。

问题是每当我更改文件时git报告它在更改的行上有行结尾差异,例如,如果原始行是

string s;

,更改的行是

string sucks;

git diff将更改显示为

string sucks;^M

看起来Git认为repo中的文件仍然有LF结尾(因为它们在过去被标准化了?)。 ^ M会产生大量的视觉噪音,我不确定这是否是其他任何问题的症状。我不明白为什么Git会报告差异,因为我在之前的提交中检查了所有带有CRLF结尾的文件,实际上是在此之前的提交。

那么为什么我会得到这些“假的”差异,我怎么能摆脱它们呢?

1 个答案:

答案 0 :(得分:5)

哇噢!我想我找到了答案。本网站http://lostechies.com/keithdahlby/2011/04/06/windows-git-tip-hide-carriage-return-in-diff/建议

git config [--global] core.whitespace cr-at-eol

这确实关闭了&#34; git diff&#34;起来。当然,最好的解决方案是在.gitattributes文件中执行等效操作,以使其与repo一致,并且不依赖于用户的设置。

.gitattributes的明确设置

花了一些时间在Linux和Windows上尝试使用repos,并使用具有Unix和Windows行结尾的文件,我相信如果你只是给你的git repo,那么整个行尾问题就可以消失了。 gitattributes文件有两行:

* -text
* whitespace=cr-at-eol

第一行阻止git执行任何行结束规范化,第二行停止git-diff突出显示行末尾的CR字符。我能找到的唯一不足之处是如果你将一个文件从DOS转换为Unix,反之亦然:git-diff会将文件显示为已更改,但它没有突出显示原因,而只是显示每行删除然后添加。我可以忍受这个,因为它是一种罕见的操作(或应该是)。

以上将行结束管理的负担放在提交者身上。这应该是,我不相信我的VCS工具应该尝试做魔术,成千上万的网页和关于git处理行结尾的问题证明他们在这里作出了错误的决定。

<强>变体形式

如果用

替换第一行
* eol=lf

然后文件将始终在工作目录中有LF结尾。这对于必须在Unix和Windows上运行的存储库来说非常方便,例如&#34; .dotfiles&#34;。同样eol=crlf将强制Windows样式行结尾。 警告这也会转换二进制文件中的CRLF!请参阅我在how to config git repo so that all files are stored with line-ending LF ( not 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 {} "\\;"  

然后,您可以在回购的根目录中执行git godosgit gounix,将所有文本文件结尾设置为其中一个。的 n.b。以上只适用于当前分支中的文件。我还没有找到转换每个分支中每个文件的方法。

<强>参考

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别名:`find -exec` in git alias