Git最好的CRLF(回车,换行)处理策略是什么?

Dan*_*phe 588 git cross-platform newline eol

我尝试使用CRLF结束行提交文件,但失败了.

我花了整整一天的时间在我的Windows计算机上尝试不同的策略,几乎被迫停止尝试使用Git而是尝试使用Mercurial.

每个答案只能分享一个最佳实践.

Dan*_*phe 732

在提出这个问题差不多四年后,我终于找到了一个完全满足我的答案!

请参阅github中的详细信息:帮助处理行结尾的帮助指南 .

Git的允许您设置为结束直接使用回购性质的行文本属性.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
Run Code Online (Sandbox Code Playgroud)

对于最流行的编程语言,有一个方便的即用型.gitattributes文件集合.让你入门是有用的.

一旦你创建或调整了你的.gitattributes,你应该执行一次又一次的所有行结束重新规范化.

请注意,在应用程序中打开项目的Git仓库后,GitHub Desktop应用程序可以建议并创建一个.gitattributes文件.要尝试此操作,请单击齿轮图标(位于右上角)>存储库设置...>行结尾和属性.系统会要求您添加建议.gitattributes,如果您同意,该应用程序还将对存储库中的所有文件执行标准化操作.

最后,Mind the Your Line的文章提供了更多背景知识,并解释了Git如何在手头的事情上发展.我认为这需要阅读.

您的团队中可能有用户使用EGit或JGit(Eclipse和TeamCity等工具使用它们)来提交更改.然后你运气不好,正如@gatinueta在这个答案的评论中解释的那样:

如果您的团队中有人使用Egit或JGit,这个设置将无法完全满足您,因为这些工具只会忽略.gitattributes并愉快地检查CRLF文件https://bugs.eclipse.org/bugs/show_bug.cgi? ID = 342372

一个技巧可能是让他们在另一个客户端提交他们的更改,比如SourceTree.然后我们的团队更喜欢Eclipse的EGit工具,用于许多用例.

谁说软件很简单?: - /

  • 对于Windows,我通常倾向于设置全局`core.autocrlf = false` - 我更喜欢LF无处不在,但是像Visual Studio这样的一些Windows工具坚持在某些文件中使用CRLF结尾(甚至将它们混合在一起...... ); 不是线路结尾是最安全的选择.如果你知道你在做什么,我可能会使用`core.autocrlf = input`并为你知道对行结尾敏感的Windows上的项目设置例外.正如其他人所指出的,现在每个体面的文本编辑器都支持LF结尾.我实际上认为`core.autocrlf = true`可能会导致比它阻止更多的麻烦. (19认同)
  • 小心分享Windows` .gitattributes`? (7认同)
  • 如果你的团队中有人使用Egit,这个设置将不会完全满足你,因为egit将忽略.gitattributes并愉快地签入CRLF文件https://bugs.eclipse.org/bugs/show_bug.cgi?id=342372 (4认同)
  • 我还建议使用 `*.sh text eol=lf` (3认同)

Joh*_*kin 114

不要转换行结尾.解释数据并不是VCS的工作 - 只需存储和版本化即可.无论如何,每个现代文本编辑器都可以读取两种行结尾.

  • 不同意.所有平台上的原生换行都很方便. (135认同)
  • Git有一个不转换行结尾的选项,它是autocrlf = false,除非你正在进行跨平台开发,比如Mono,最好在Windows下运行时保持为假,如果要开发开源,则设置为true对于单声道. (32认同)
  • 借调.如果您遇到不一致的行结尾问题,那么最好的解决方案就是对使用错误编辑器设置的人大喊大叫,直到他们修复它为止. (25认同)
  • 除了CRLF之外,Visual Studio还是一个PITA. (24认同)
  • 行结尾的问题是计算正确的差异.所以答案是错误的和误导性的. (22认同)
  • @escouten - 在Windows上,你没有_have_在crlf中有文件,只是Windows编辑器可以默认配置为以这种格式保存.更改编辑器选项.在Windows上打开"lf"eol文件不是问题.(如果您使用记事本作为主编辑,那么,停止.)在许多情况下,您仍然需要"原始"的eol,而不是转换为eol; 例如,如果将bash脚本转换为crlf,则无法在cygwin下运行bash脚本; 单元测试可能具有此转换"损坏"的输入/输出文件等. (13认同)
  • 如果不解释要使用哪些设置来避免转换行结尾,这个答案就不是很有用了. (12认同)
  • 我对这个策略感到满意,但是 - 我做错了什么? - 如果我没有使用dos2unix手动转换文件,或者如果我没有使用autocrlf配置它,git会拒绝我的提交.像"补丁包含可疑线"之类的东西,还有一些时候,"在eol上可疑的空白" (3认同)
  • 如果你在Windows上工作,你真的没有太多选择.您需要在Windows上使用CRLF模式的文件,而在Unix-ish平台上只需要LF. (3认同)
  • +1,当您的团队在同一个仓库中共享.bat和.sh文件时,不要修改EOL. (2认同)

Cor*_*ory 81

autocrlf=input除非你真的知道自己在做什么,否则你几乎总是想要.

下面的一些附加背景:

它应该是core.autocrlf=true你喜欢DOS结束还是core.autocrlf=input喜欢unix-newlines.在这两种情况下,您的Git存储库将只有LF,这是正确的东西.唯一的理由core.autocrlf=false是自动启发式可能会错误地将某些二进制文件检测为文本,然后您的磁贴将被损坏.因此, core.safecrlf引入了一个选项来警告用户是否发生了不可逆转的变化.事实上,有两种不可逆转的可能性 - 文本文件中的混合行尾,在这种规范化中是可取的,因此可以忽略此警告,或者(非常不可能)Git错误地将二进制文件检测为文本.然后你需要使用属性来告诉Git这个文件是二进制文件.

上面的段落最初是从gmane.org上的一个帖子中提取出来的,但它已经失败了.

  • core.autocrlf = true是个糟糕的主意.我对该选项没有任何麻烦,而且你必须记住在克隆存储库时设置它. (35认同)
  • 为什么它是"正确的事"? (30认同)
  • 除非你知道自己在做什么,否则不要使用autocrlf = true.如果你在DOS/Win中开发,那么autocrlf = false将使远程和本地repo之间的结尾保持相同,并且几乎在所有情况下都是最佳选择. (28认同)
  • **赞成投票,保留.**介绍段落无益.`core.autocrlf = input`是规范的答案.对于大多数用例,`core.autocrlf = true`和`core.autocrlf = false`过于热心(......当然是相反但同样可怕的方式),因而具有内在的破坏性."Git for Windows"应该_really_附带"Checkout as-is,提交Unix风格的行结尾"(即`core.autocrlf = input`)作为其默认的换行策略.它没有.所以我们在这里--_in frickin'2015_ - 仍在无休止地争论这个. (20认同)
  • @Chris - 如果您的开发人员拥有Windows和多平台项目,而某些多平台开发人员在OSX或Linux上工作,该怎么办?那么最好的选择不应该是autocrlf = true吗? (13认同)
  • 我怀疑这个答案是错误的.这个建议与我在其他地方读到的内容不一致. (3认同)
  • 这将是一个有意义的场景,但它不是一个常见的场景,所以这就是为什么它作为默认值没有意义,而是在每个回购的基础上. (2认同)
  • 如果你能够以正确的方式初始化repo(或在某些时候剥离CRLF/CR),则autocrlf = true是好的.许多编辑(特别是Windows下的编辑器?)会产生CRLF并且混合换行存在问题.例如:最小的变化可能导致每一行的转换.当CR与CRLF混合时,git-diff也存在问题. (2认同)
  • @BrettRyan - `autocrlf = true`永远不是最安全的选择. (2认同)
  • 我不同意,我从事的许多项目中,Windows 开发人员可能会弄乱行结尾。不过,我现在在所有项目上都使用“.gitattributes”。 (2认同)

luk*_*mdo 57

在混合环境中(Microsoft + Linux + Mac)获得关于行尾的一致性的两种替代策略:

A.全局所有存储库设置

1)将所有转换为一种格式

find . -type f -not -path "./.git/*" -exec dos2unix {} \;
git commit -a -m 'dos2unix conversion'
Run Code Online (Sandbox Code Playgroud)

2)设置core.autocrlfinput在Linux/UNIX或true在MS Windows(库或全球)

git config --global core.autocrlf input
Run Code Online (Sandbox Code Playgroud)

3)[可选]设置core.safecrlftrue(停止)或warn(唱歌:)添加额外的保护比较,如果反向换行转换将导致相同的文件

git config --global core.safecrlf true
Run Code Online (Sandbox Code Playgroud)


B.或每个存储库设置

1)将所有转换为一种格式

find . -type f -not -path "./.git/*" -exec dos2unix {} \;
git commit -a -m 'dos2unix conversion'
Run Code Online (Sandbox Code Playgroud)

2)将.gitattributes文件添加到您的存储库

echo "* text=auto" > .gitattributes
git add .gitattributes
git commit -m 'adding .gitattributes for unified line-ending'
Run Code Online (Sandbox Code Playgroud)

不要担心你的二进制文件--Git应该足够聪明.


有关safecrlf/autocrlf变量的更多信息

  • 警告:在运行`find`行之前,请注意:使用Git for Windows的`dos2unix`有一种特殊的(IMO愚蠢和危险)行为,没有参数:它不是改为UNIX,而是*切换*换行格式(DOS < - > UNIX) (6认同)
  • **全局方法**==设置并忘记所有回购与**每回购**==不要求其他人更改其全局配置. (5认同)
  • `dos2unix`是一个命令行工具,取决于您可能需要另外安装的系统 (4认同)
  • 它们不是独家的,您可以同时使用这两种方法.另外,使用`dos2unix`时要非常小心 - 存在[破坏`.git/index`](http://stackoverflow.com/questions/1115854/index-file-corrupt)的风险,我们不需要将其应用于每个文件.最好使用像`find ./ -name"*.html"`这样的东西,并指定你想要应用它的文件. (2认同)
  • 另一个警告:不要在DOS2UNIX的.git文件夹中。只是说。 (2认同)

Gre*_*ill 10

尝试将core.autocrlf配置选项设置为true.还看看core.safecrlf选项.

实际上它听起来core.safecrlf可能已经在您的存储库中设置,因为(强调我的):

如果对于core.autocrlf的当前设置不是这种情况,git将拒绝该文件.

如果是这种情况,那么您可能需要检查文本编辑器是否配置为一致地使用行结尾.如果文本文件包含LF和CRLF行结尾的混合,则可能会遇到问题.

最后,我觉得简单地"使用你给你的东西"并在Windows上使用LF终止线的建议将导致比它解决的更多问题.Git有以上选项来尝试以合理的方式处理行结尾,因此使用它们是有意义的.

  • 通过 .gitattributes 文件使用存储库范围的设置不是更好吗?只是想知道:强迫每个用户在他的机器上处理他的行结束设置是不方便的......或者还有其他缺点吗? (2认同)

Lan*_*and 9

core.autocrlf=false在我的Visual Studio 2010项目中检出后,使用停止的所有文件被标记为已更新.开发团队的另外两个成员也使用Windows系统,因此混合环境没有发挥作用,但存储库附带的默认设置始终将所有文件标记为克隆后立即更新.

我想底线是找到适合您环境的CRLF设置.特别是因为在我们Linux机箱上的许多其他存储库中,设置autocrlf = true会产生更好的结果.

20多年后,我们仍在处理操作系统之间的线路结束差异......很难过.

  • @Kyralessa"更正确"仍假装计算机是打字机,但事实并非如此.顺便说一下.保持打字机类比没有任何意义,因为这不是最终用户将要处理的事情,并且两个字符而不是一个字符是没有意义的. (39认同)
  • @ orange80,差距是不幸的,但没有理由把它称为Windows的错.LF也许从极简主义的角度来看是有道理的; 但根据CR和LF的含义,CRLF更有意义."回车"是指返回到行的开头; "换行"意味着直接向下移动到下一行,而不是到下一行的开头.从语义的角度来看,Windows在两者中都更为正确:移回到开头(CR)然后向下移动一行(LF). (31认同)
  • 此外,如果 CRLF 是“更正确的”,因为文本文件换行符实际上既是“向下移动一行”又是“移动到行首”,那么只有 CR 会导致文本编辑器用以下行。我知道没有真正支持这一点的编辑器,这意味着需要将 CRLF 和 CR 表示为不同的东西,实际上并不存在。 (2认同)

kie*_*wic 7

这些是与MacLinux用户共享代码的WindowsVisual Studio用户的两个选项.有关扩展说明,请阅读gitattributes手册.

*text = auto

在您的repo .gitattributes文件中添加:

*   text=auto
Run Code Online (Sandbox Code Playgroud)

这将规范化LFrepo中具有行结尾的所有文件.

根据您的操作系统(core.eol设置),工作树中的文件将LF针对基于Unix的系统或CRLFWindows系统进行标准化.

这是Microsoft .NET repos使用的配置.

例:

Hello\r\nWorld
Run Code Online (Sandbox Code Playgroud)

将在回购中标准化为:

Hello\nWorld
Run Code Online (Sandbox Code Playgroud)

在结帐时,Windows中的工作树将转换为:

Hello\r\nWorld
Run Code Online (Sandbox Code Playgroud)

结帐时,Mac中的工作树将保留为:

Hello\nWorld
Run Code Online (Sandbox Code Playgroud)

注意:如果您的repo已包含未规范化的git status文件,则下次对其进行任何更改时,将显示这些文件已完全修改,以及其他用户稍后合并其更改可能会很麻烦.有关更多信息,请参阅更改行结尾后刷新存储库.

core.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行结尾的文件引入到repo中.
  • 大多数Mac用户使用autocrlf = input并可能获得带有CRLF文件结尾的文件,可能来自Windows用户core.autocrlf = false.

  • Windows 用户的命令为“git config --global core.autocrl true”。你的意思是“git config --global core.autocrlf true”。 (2认同)

Mar*_* An 6

我花了几个小时来想尽最大可能地使用.gitattributes,最终意识到我不能指望它。
不幸的是,只要存在基于JGit的编辑器(无法.gitattributes正确处理),安全的解决方案就是即使在编辑器级别也将LF强制到处。

使用以下anti-CRLF消毒剂。

-更新2-

git client的dafaults在大多数情况下都可以使用。即使您只有Windows仅客户机,Linux仅客户机或两者都有。这些是:

  • Windows: 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
Run Code Online (Sandbox Code Playgroud)

另外,与git document相比,我强烈建议不要使用git config --global core.autocrlf false(如果您只有Windows客户端)。设置为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)。
  • 如果通过执行上述命令找到任何此类文件,请更正它们。这涉及(至少在Linux中):
    • 更改文件
    • 还原更改(文件仍显示为更改)
    • 提交
  • 仅使用最低限度 .gitattributes
  • 指示用户core.autocrlf将上述内容设置为其默认值。
  • 请勿将100%计为存在.gitattributes。IDE的git-client可能会忽略它们或将它们区别对待。

如前所述,可以在git属性中添加一些内容:

# Always checkout with LF
*.sh            text eol=lf
# Always checkout with CRLF
*.bat           text eol=crlf
Run Code Online (Sandbox Code Playgroud)

我认为可以使用其他一些安全选项,.gitattributes而不是对二进制文件使用自动检测:

  • -text(例如,对于*.zip*.jpg文件:将不被视为文本。因此,将不尝试行尾转换。通过转换程序可能会产生差异)
  • text !eol(例如,对于*.java*.html::被视为文本,但未设置eol样式首选项。因此使用客户端设置。)
  • -text -diff -merge(例如*.hugefile::不被视为文本。不能进行差异/合并)

-以前的更新-

客户端错误提交文件的一个痛苦示例

netbeans 8.2(在Windows上)将错误地提交所有带有CRLF的文本文件,除非您已明确将其设置core.autocrlf为global。这与标准的git客户端行为相矛盾,并在以后更新/合并时引起很多问题。这就是使某些 文件即使在还原时也显得不同(尽管它们没有区别)的原因。
即使您.gitattributes向项目中添加了正确的代码,在netbeans中也会发生相同的行为。

提交后使用以下命令,至少可以帮助您及早发现git repo是否存在行尾问题: git grep -I --files-with-matches --perl-regexp '\r' HEAD


Joh*_*pel 5

这只是一个变通的解决方案:

通常情况下,使用 git 附带的解决方案。这些在大多数情况下都很好用。如果您通过设置.gitattributes在基于 Windows 和 Unix 的系统上共享开发,则强制使用 LF 。

就我而言,有超过 10 名程序员在 Windows 中开发一个项目。这个项目是用 CRLF 签入的,没有强制执行 LF 的选项。

一些设置是在我的机器上内部编写的,对 LF 格式没有任何影响;因此,每次小文件更改时,某些文件都会全局更改为 LF。

我的解决方案:

Windows-Machines: 让一切照原样。什么都不在乎,既然你是一个默认的 windows '孤狼' 开发者,你必须像这样处理:“世界上没有其他系统,是吗?”

Unix-机器

  1. 将以下行添加到配置[alias]部分。此命令列出所有更改的(即修改的/新的)文件:

    lc = "!f() { git status --porcelain \
                 | egrep -r \"^(\?| ).\*\\(.[a-zA-Z])*\" \
                 | cut -c 4- ; }; f "
    
    Run Code Online (Sandbox Code Playgroud)
  2. 将所有这些更改的文件转换为 dos 格式:

    unix2dos $(git lc)
    
    Run Code Online (Sandbox Code Playgroud)
  3. 可选...

    1. 为此操作创建一个 git hook以自动执行此过程

    2. 使用 params 并包含它并修改grep函数以仅匹配特定的文件名,例如:

      ... | egrep -r "^(\?| ).*\.(txt|conf)" | ...
      
      Run Code Online (Sandbox Code Playgroud)
    3. 随意使用额外的快捷方式使其更加方便:

      c2dos = "!f() { unix2dos $(git lc) ; }; f "
      
      Run Code Online (Sandbox Code Playgroud)

      ...并通过键入来触发转换后的内容

      git c2dos
      
      Run Code Online (Sandbox Code Playgroud)