Git 的最佳 CRLF(回车、换行)处理策略是什么?
-
05-07-2019 - |
题
解决方案
在提出这个问题差不多四年之后,我终于来了 找到完全满足我的答案!
请参阅 github:help 指南中的详细信息 处理行结尾。
Git允许您设置a的行结束属性 repo直接使用文本属性
.gitattributes
文件。此文件已提交到 repo并覆盖core.autocrlf
设置, 允许您确保所有人的行为一致 用户,无论他们的git设置如何。
因此
这样做的好处就是你的终点 配置现在与您的存储库和您一起旅行 不需要担心是否合作者 有适当的全局设置。
以下是 .gitattributes
文件的示例
# Auto detect text files and perform LF normalization
* text=auto
*.cs text diff=csharp
*.java text diff=java
*.html text diff=html
*.css text
*.js text
*.sql text
*.csproj text merge=union
*.sln text merge=union eol=crlf
*.docx diff=astextplain
*.DOCX diff=astextplain
# absolute paths are ok, as are globs
/**/postinst* text eol=lf
# paths that don't start with / are treated relative to the .gitattributes folder
relative/path/*.txt text eol=lf
对于最流行的编程语言,有一个方便的即用型.gitattributes文件集合。让你开始是有用的。
创建或调整 .gitattributes
后,您应该执行一次性的线路结束重新规范化。
请注意, GitHub桌面应用可以建议并创建 .gitattributes
在应用程序中打开项目的Git仓库后出现文件。要尝试此操作,请单击齿轮图标(位于右上角)>存储库设置...>行结尾和属性。系统会要求您添加推荐的 .gitattributes
,如果您同意,该应用程序还会对您的存储库中的所有文件执行标准化。
最后,介意你的行尾文章 提供了更多背景知识,并解释了Git如何发展 关于手头的事情。我认为需要阅读。
您的团队中可能有用户使用EGit或JGit(Eclipse和TeamCity等工具使用它们)来提交更改。然后你运气不好,正如@gatinueta在这个答案的评论中解释的那样:
如果您的团队中有人使用Egit或JGit,此设置将无法完全满足您,因为这些工具将忽略.gitattributes并愉快地检入CRLF文件 https://bugs.eclipse.org/bugs/show_bug.cgi?id=342372
一个技巧可能是让他们在另一个客户端提交他们的更改,比如 SourceTree 。然后我们的团队更喜欢Eclipse的EGit用于许多用例的工具。
谁说软件很简单? : - /
其他提示
不要转换行结尾。解释数据并不是VCS的工作 - 只需存储和版本化即可。无论如何,每个现代文本编辑器都可以读取两种行结尾。
除非你真的知道自己在做什么,否则你几乎总是想要 autocrlf = input
。
以下一些其他背景信息:
如果您愿意,它应该是
core.autocrlf = true
如果您愿意,DOS结束或core.autocrlf =输入
UNIX的换行。在这两种情况下,您的Git存储库都将 只有LF,这是正确的事情。唯一的core.autocrlf = false
的参数是自动的 启发式可能会错误地将某些二进制文件检测为 然后你的瓷砖将被破坏。所以, 引入了core.safecrlf
选项来警告用户是否 发生了不可逆转的变化。实际上,有两个 不可逆转的变化的可能性 - 混合 在文本文件中以行结尾,在此规范化中 希望,所以这个警告可以忽略,或 (非常不可能)Git错误地检测到了你的 二进制文件作为文本。然后你需要使用属性 告诉Git这个文件是二进制文件。
以上段落最初是从gmane.org上的一个帖子中删除的,但它已经失效了。
在混合环境(Microsoft + Linux + Mac)中获得关于行结尾的一致的两种替代策略: 结果
甲。全球按所有存储库设置
1)将全部转换为一种格式 强>
find . -type f -not -path "./.git/*" -exec dos2unix {} \;
git commit -a -m 'dos2unix conversion'
2)在Linux / UNIX上将 core.autocrlf
设置为 input
,或在MS Windows上设置 true
(存储库或全局)强>
git config --global core.autocrlf input
3)[可选]将 core.safecrlf
设置为 true
(停止)或 warn
(唱歌:)以添加额外的保护比较反转的换行符转换是否会产生相同的文件
git config --global core.safecrlf true
结果
B中。或每个存储库设置
1)将全部转换为一种格式 强>
echo "* text=auto" > .gitattributes
git add .gitattributes
git commit -m 'adding .gitattributes for unified line-ending'
2)将 .gitattributes
文件添加到您的存储库
不要担心你的二进制文件--Git应该对它们足够聪明。
尝试将 core.autocrlf
配置选项设置为 true
。另请参阅 core.safecrlf
选项。
实际上听起来像 core.safecrlf
可能已经在您的存储库中设置了,因为(强调我的):
如果对于core.autocrlf的当前设置不是这种情况, git将拒绝该文件。
如果是这种情况,那么您可能需要检查文本编辑器是否配置为一致地使用行结尾。如果文本文件包含LF和CRLF行结尾的混合,则可能会遇到问题。
最后,我觉得建议只是“使用你给的东西”。并在Windows上使用LF终止行将导致比它解决的更多问题。 Git有以上选项来尝试以合理的方式处理行结尾,因此使用它们是有意义的。
使用 core.autocrlf = false
,一旦我在 Visual  Studio  2010 项目。开发团队的另外两个成员也使用Windows系统,因此混合环境没有发挥作用,但是存储库附带的默认设置始终将所有文件标记为在克隆后立即更新。
我想最重要的是找到适合您环境的CRLF设置。特别是因为在Linux盒子上的许多其他存储库中设置 autocrlf = true
会产生更好的结果。
20多年后,我们仍在处理操作系统之间的行结束差异......悲伤。
这是两个选项 视窗 和 视觉工作室 与其共享代码的用户 苹果 或者 Linux 用户。有关详细说明,请阅读 gitattributes手册.
* 文本=自动
在你的仓库中 .gitattributes
文件添加:
* text=auto
这将标准化所有文件 LF
存储库中的行结尾。
并取决于您的操作系统(core.eol
设置),工作树中的文件将被标准化为 LF
对于基于 Unix 的系统或 CRLF
对于 Windows 系统。
这是配置 微软.NET 回购协议的使用。
例子:
Hello\r\nWorld
将在存储库中始终标准化为:
Hello\nWorld
结帐时,Windows 中的工作树将转换为:
Hello\r\nWorld
结账时,Mac 中的工作树将保留为:
Hello\nWorld
笔记:如果您的存储库已包含未标准化的文件,
git status
下次您对这些文件进行任何更改时,会将这些文件显示为已完全修改,并且其他用户稍后合并其更改可能会很痛苦。看 更改行结尾后刷新存储库 了解更多信息。
核心.autocrlf = true
如果 text
中未指定 .gitattributes
文件,Git 使用 core.autocrlf
配置变量来确定是否应转换文件。
对于 Windows 用户来说, git config --global core.autocrlf true
是一个很好的选择,因为:
- 文件标准化为
LF
行结尾 仅当添加时 到回购协议。如果存储库中存在未标准化的文件,则此设置不会影响它们。 - 所有文本文件都转换为
CRLF
工作目录中的行结尾。
这种方法的问题在于:
- 如果您是 Windows 用户
autocrlf = input
, ,你会看到一堆文件LF
行结尾。对于团队的其他成员来说这不是一个危险,因为你的提交仍然会被标准化LF
行结尾。 - 如果您是 Windows 用户
core.autocrlf = false
, ,你会看到一堆文件LF
行结尾,您可以使用以下内容引入文件CRLF
行结尾到存储库中。 - 大多数 Mac 用户使用
autocrlf = input
并且可能会获取文件CRLF
文件结尾,可能来自 Windows 用户core.autocrlf = false
.
这只是解决方法解决方案:
在正常情况下,请使用git附带的解决方案。这些在大多数情况下都很有效。如果您通过设置 .gitattributes 在基于Windows和Unix的系统上共享开发,则强制为LF。
在我的案例中,有> 10名程序员在Windows中开发项目。该项目已通过CRLF签入,没有强制选择LF的选项。
某些设置在我的机器上内部写入,对LF格式没有任何影响;因此,在每次小文件更改时,一些文件全局更改为LF。
我的解决方案:
<强> Windows的机器:强> 让一切都保持原样。什么都不关心,因为你是一个默认的Windows'孤狼'开发者,你必须像这样处理:“广阔的世界里没有其他系统,是吗?”
<强> Unix的机强>
-
将以下行添加到配置的
[alias]
部分。此命令列出所有已更改(即已修改/新建)的文件:lc = "!f() { git status --porcelain \ | egrep -r \"^(\?| ).\*\\(.[a-zA-Z])*\" \ | cut -c 4- ; }; f "
-
将所有已更改的文件转换为dos格式:
unix2dos $(git lc)
-
可选...
-
为此创建一个git hook 自动化此过程的行动
-
使用params并包含它并修改
grep
函数以仅匹配特定的文件名,例如:... | egrep -r "^(\?| ).*\.(txt|conf)" | ...
-
使用其他快捷方式随意使其更方便:
c2dos = "!f() { unix2dos $(git lc) ; }; f "
...并通过输入
来解锁转换后的内容git c2dos
醇> -
我花了几个小时想出最好的使用方法 .gitattributes
, ,最终意识到,我不能指望它。
不幸的是,只要基于 JGit 的编辑器存在(它无法处理 .gitattributes
正确),安全的解决方案是在所有地方强制使用 LF,甚至在编辑器级别也是如此。
使用以下内容 anti-CRLF
消毒剂。
Windows/Linux 客户端:
core.autocrlf=input
坚定的
.gitattributes
:* text=auto eol=lf
坚定的
.editorconfig
(http://editorconfig.org/) 这是一种标准化格式,与编辑器插件相结合:
--- 更新 2 ---
git 客户端的默认设置在大多数情况下都可以工作。即使您只有 Windows 客户端、Linux 客户端或两者都有。这些都是:
- 视窗:
core.autocrlf=true
表示在签出时将行转换为 CRLF,在添加文件时将行转换为 LF。 - linux:
core.autocrlf=input
意味着在签出时不转换行(不需要,因为文件预计以 LF 提交)并在添加文件时将行转换为 LF(如果需要)。
该属性可以在不同的范围内设置。我建议明确设置 --global
范围,以避免最后描述的一些 IDE 问题。
git config core.autocrlf
git config --global core.autocrlf
git config --system core.autocrlf
git config --local core.autocrlf
git config --show-origin core.autocrlf
我也强烈地 不鼓励 使用 git config --global core.autocrlf false
(如果您只有 Windows 客户端)与建议的相反 git 文档. 。设置为 false 将在存储库中提交带有 CRLF 的文件。但确实没有理由。您永远不知道是否需要与 Linux 用户共享该项目。另外,对于加入该项目的每个客户来说,这都是一个额外的步骤,而不是使用默认值。
现在对于一些特殊情况的文件(例如 *.bat
*.sh
)您希望使用 LF 或 CRLF 检出它们,您可以使用 .gitattributes
给我总结一下 最佳实践 是:
- 确保每个非二进制文件都在 git repo 上使用 LF 提交(默认行为)。
- 使用此命令确保没有使用 CRLF 提交文件:
git grep -I --files-with-matches --perl-regexp '\r' HEAD
(笔记: 在 Windows 客户端上只能通过git-bash
并且仅在 Linux 客户端上使用编译时--with-libpcre
在./configure
). - 如果执行上述命令发现任何此类文件,请更正它们。
- 仅使用最低限度
.gitattributes
- 指导用户设置
core.autocrlf
如上所述为其默认值。 - 不要 100% 相信存在
.gitattributes
. 。IDE 的 git 客户端可能会忽略它们或以不同的方式对待它们。
如前所述,可以在 git 属性中添加一些内容:
# Always checkout with LF
*.sh text eol=lf
# Always checkout with CRLF
*.bat text eol=crlf
我认为还有其他一些安全的选择 .gitattributes
而不是对二进制文件使用自动检测:
-text
(例如对于*.zip
或者*.jpg
文件:不会被视为文本。因此,不会尝试进行行结束转换。通过转换程序可能可以实现差异)text !eol
(例如。为了*.java
,*.html
: :视为文本,但未设置 eol 样式首选项。因此使用客户端设置。)-text -diff -merge
(例如对于*.hugefile
: :不被视为文本。无法进行差异/合并)
--- 之前的更新 ---
一 痛苦的例子 错误提交文件的客户端:
网豆 8.2 (在 Windows 上),将错误地提交所有文本文件 CRLF,除非 你有 明确地 放 core.autocrlf
作为全球性的. 。这与标准 git 客户端行为相矛盾,并在更新/合并时导致很多问题。这就是让一些人 文件看起来不同 (虽然他们不是) 即使当你恢复时.
即使您添加了正确的内容,netbeans 中也会发生相同的行为 .gitattributes
到你的项目。
提交后使用以下命令,至少可以帮助您尽早检测 git 存储库是否存在行结束问题: git grep -I --files-with-matches --perl-regexp '\r' HEAD