Git规范化后的行尾符

5
这个换行符问题让我头疼不已...
背景:历史上,我使用了core.autocrlf设置,但我发现不同的代码库表现不佳(我在Windows上工作,有些代码库需要LF结尾,有些则需要CRLF结尾)。因此,我试图摆脱这种设置,在每个代码库中使用.gitattributes文件(我希望Git保持沉默,让我管理换行符!)。所以现在我把core.autocrlf设置为false,并为我正在处理的Visual Studio项目创建了一个.gitattributes文件,内容如下:
# 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 这几乎是完美的。
问题在于,每当我更改一个文件时,git会报告更改的行存在行结尾差异,例如,如果原始行是:
string s;

修改后的行为:

string sucks;

git diff 展示的是变更内容:

string sucks;^M

似乎Git认为仓库中的文件仍然具有LF结尾(因为它们在过去被标准化了?)。^M会导致大量视觉噪音,我不确定这是否是其他任何症状。我不明白为什么Git会报告差异,因为我已经在之前的提交中检查了所有带有CRLF结尾的文件,事实上,就在这个提交之前。
那么我为什么要得到这些“虚假”的差异,如何摆脱它们?

你使用的编辑器是什么?你确定它没有插入不同的换行符吗? - BlackVegetable
1个回答

7

太棒了!我认为我找到了一个答案。这个网站http://lostechies.com/keithdahlby/2011/04/06/windows-git-tip-hide-carriage-return-in-diff/建议执行以下操作:

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

这确实可以让 "git diff" 保持安静。当然,最好的解决方案是在 .gitattributes 文件中做相应设置,以便它随仓库而存在,不依赖于用户的设置。

.gitattributes 的确定性设置

在 Linux 和 Windows 上尝试了一些仓库,并使用具有 Unix 和 Windows 行结尾的文件进行了一些实验后,我相信如果您只给您的 git 仓库一个包含两行内容的 .gitattributes 文件,整个行尾问题就可以消失:

* -text
* whitespace=cr-at-eol

第一行代码阻止了git对行尾进行任何标准化处理,第二行代码阻止了git-diff在行末高亮显示CR字符。我唯一发现的缺点是,如果你将一个文件从DOS转换为Unix或者反过来,会出现一些奇怪的情况:git-diff会显示文件已更改,但它不会突出显示原因,而是只显示每一行被删除然后添加的情况。我可以接受这种情况,因为这种操作非常罕见(或应该是罕见的)。
以上内容将行尾管理的负担放在了提交者身上。这正是应该的,我认为我的版本控制工具不应该试图做魔法,有关git处理行尾的成千上万的网页和问题证明他们在这里做出了错误的决定。
变体:
如果您将第一行替换为
* eol=lf

如果在工作目录中设置了LF结尾,则文件将始终具有LF结尾。这对于必须跨Unix和Windows工作的存储库(如“.dotfiles”)非常方便。同样,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别名提供了一种快速将仓库中所有文本文件从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,以将所有文本文件结尾设置为其中之一。请注意,上述内容仅适用于当前分支中的文件。我还没有找到一种方法来转换每个分支中的每个文件。
参考资料: 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

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