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

我尝试使用以crlf结尾的行提交文件,但失败了。

我花了一整天的时间在我的Windows电脑上尝试不同的策略,几乎要停止尝试使用Git,而是尝试水银

如何正确处理CRLF行结束符?

242252 次浏览

不要转换行结束符。VCS的工作不是解释数据——只是存储和版本它。每个现代文本编辑器都可以读取这两种行尾。

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

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

如果这不是当前设置的核心的情况。autocrlf # EYZ0。

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

最后,我觉得在Windows上简单地“使用您所给予的”和使用LF终止行的建议会导致比它解决的问题更多的问题。Git有上述选项来尝试以合理的方式处理行结束符,因此使用它们是有意义的。

你几乎总是想要autocrlf=input,除非你真的知道你在做什么。

下面是一些附加的上下文:

如果你喜欢,它应该是core.autocrlf=true DOS结尾或core.autocrlf=input(如果您喜欢) unix-newlines。在这两种情况下,您的Git存储库都可以 只有LF,这是正确的事情。唯一的 core.autocrlf=false的参数是自动的 启发式可能错误地检测一些二进制作为文本 然后你的瓷砖就会被损坏。所以, core.safecrlf选项用于警告用户 不可逆转的变化发生了。事实上,有两个 不可逆转的变化的可能性——混合 在文本文件的行结束,在这个规范化是 可取的,所以这个警告可以被忽略,或者 (不太可能)Git错误地检测到您的 二进制文件作为文本。然后需要使用属性 告诉Git这个文件是二进制的

上面这段话最初是从gmane.org上的一个帖子中截取的,但现在已经删除了。

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

我认为最重要的是找到适合您的环境的CRLF设置。特别是在我们的Linux盒子上的许多其他存储库中,设置autocrlf = true会产生更好的结果。

20多年后,我们仍然在处理操作系统之间的行尾差异……伤心。

问了这个问题快四年了,我终于 发现# EYZ0 !< / p >

详见github:帮助的指南 # EYZ0。< / p >

Git允许你设置一行结束属性 文件中的文本属性直接执行repo # EYZ1文件。该文件被提交 回购和覆盖core.autocrlf设置, 允许您确保所有人的行为一致

因此

这样做的好处是你的行结束 现在,配置随存储库和您一起传递 不需要担心是否合作者 有正确的全局设置。

下面是.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,则此设置将不能完全满足您的要求,因为这些工具将忽略.git属性并愉快地检入CRLF文件https://bugs.eclipse.org/bugs/show_bug.cgi?id=342372

一个技巧可能是让他们在另一个客户机中提交他们的更改,比如SourceTree。在许多用例中,我们的团队更喜欢这个工具而不是Eclipse的EGit。

谁说软件很简单?: - /

在混合环境(微软+ Linux + Mac)中,有两种替代得到一致的的行结束策略:

A.全局所有存储库设置

  1. < p > # EYZ0

    find . -type f -not -path "./.git/*" -exec dos2unix {} \;
    git commit -a -m 'dos2unix conversion'
    
  2. < p > # EYZ3

    git config --global core.autocrlf input
    
  3. 可选地,将core.safecrlf设置为true (stop)或warn (sing:)来添加额外的保护,比较反向换行转换是否会产生相同的文件

    git config --global core.safecrlf true
    

B.或者每个存储库设置

  1. < p > # EYZ0

    find . -type f -not -path "./.git/*" -exec dos2unix {} \;
    git commit -a -m 'dos2unix conversion'
    
  2. < p > # EYZ1

    echo "* text=auto" > .gitattributes
    git add .gitattributes
    git commit -m 'adding .gitattributes for unified line-ending'
    

不要担心二进制文件——git应该对它们足够聪明。


更多关于safecrlf/ selflf变量的信息

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

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

以我为例,有10个程序员在Windows上开发一个项目。这个项目是用CRLF和没有选择强行到LF。签入的

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

我的解决方案:

< >强windows机器: 让一切顺其自然吧。什么都不关心,因为你是一个默认的windows“独狼”开发人员,你必须处理这样的问题:“在这个广阔的世界上没有其他系统了,是吗?”< / p >

unix机器上

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

    lc = "!f() { git status --porcelain \
    | egrep -r \"^(\?| ).\*\\(.[a-zA-Z])*\" \
    | cut -c 4- ; }; f "
    
  2. Convert all those changed files into dos format:

    unix2dos $(git lc)
    
  3. Optionally ...

    1. Create a git hook for this action to automate this process

    2. Use params and include it and modify the grep function to match only particular filenames, e.g.:

      ... | egrep -r "^(\?| ).*\.(txt|conf)" | ...
      
    3. Feel free to make it even more convenient by using an additional shortcut:

      c2dos = "!f() { unix2dos $(git lc) ; }; f "
      

      ... 并通过输入点燃转换的东西

      git c2dos
      

这是窗户Visual Studio用户与MacLinux用户共享代码的两个选项。更详细的解释,请阅读gitattributes手册

*文本=汽车

在回购的.gitattributes文件中添加:

*   text=auto

这将规范化repo中所有以LF结尾的文件。

根据您的操作系统(core.eol设置),工作树中的文件将被规范化为LF(基于Unix的系统)或CRLF(基于Windows的系统)。

这是Microsoft . net回购所使用的配置。

例子:

Hello\r\nWorld

将在回购中始终归一化为:

Hello\nWorld

签出时,Windows中的工作树将被转换为:

Hello\r\nWorld

签出时,Mac中的工作树将保留为:

Hello\nWorld

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

核心。独裁者= true

如果text.gitattributes文件中未指定,Git使用core.autocrlf配置变量来确定是否应该转换文件。

对于Windows用户,git config --global core.autocrlf true是一个很好的选择,因为:

  • 文件归一化为LF行结束符仅当添加时到repo。如果在repo中有未规范化的文件,此设置将不会触及它们。
  • 所有文本文件都转换为工作目录中的CRLF行结束符。

这种方法的问题在于:

  • 如果你是一个使用autocrlf = input的Windows用户,你会看到一堆以LF结尾的文件。这对团队的其他成员来说并不危险,因为您的提交仍将使用LF行结束符进行规范化。
  • 如果你是一个使用core.autocrlf = false的Windows用户,你会看到一堆以LF结尾的文件,你可以在repo中引入以CRLF结尾的文件。
  • 大多数Mac用户使用autocrlf = input,可能会从使用core.autocrlf = false的Windows用户那里获得以CRLF结尾的文件。

——UPDATE 3——(与UPDATE 2不冲突)

考虑到windows用户更喜欢在CRLF上工作,而linux/mac用户更喜欢在文本文件上使用LF。从存储库维护者的视角提供答案:

对我来说,最好的策略(要解决的问题更少)是:保持所有文本文件LF内部git回购,即使你是在开发一个只支持windows的项目。然后在他们喜欢的行结束风格上使用给客户自由,前提是他们选择一个core.autocrlf属性值,在提交文件时将尊重你的策略(回购的LF)暂存。

暂存是许多人在尝试理解如何换行策略工作时所困惑的。在为core.autocrlf属性选择正确的值之前,有必要了解以下几点:

  • 添加一个文本文件提交(暂存它)是比如把文件复制到另一个地方.git/子目录和转换上下文菜单(取决于core.autocrlf的值在您的客户端配置)。这一切都完成了本地。
  • 设置core.autocrlf就像提供一个问题的答案(在所有操作系统上都是一样的问题): "Should git-client:
    • # EYZ0 # EYZ1吗?
    • # EYZ0 # EYZ1"
  • 和可能的答案(值)是:
    • # EYZ0“# EYZ1",
    • # EYZ0“# EYZ1"
    • # EYZ0:“# EYZ1"
    • 注意这里没有& 只做一个"

幸运的是

  • git客户端默认(windows: core.autocrlf: true, linux/mac: core.autocrlf: false)将与LF-only-repo策略兼容。
    含义: windows客户端在签出存储库时默认转换为CRLF,在添加提交时默认转换为LF。linux客户端默认情况下不进行任何转换。这理论上保持你的回购只有lf。

不幸的是:

  • 可能有GUI客户端不尊重git# EYZ0值
  • 可能有些人不使用一个值来尊重你的lf-回购策略。例如,他们使用core.autocrlf=false并添加了一个带有CRLF的文件来提交。

检测上述客户端提交的ASAP非lf文本文件你可以遵循——update 2上的描述:(git grep -I --files-with-matches --perl-regexp '\r' HEAD,在使用:--with-libpcre标记编译的客户端上)

# EYZ1。我作为一个回购维护者保留了一个git.autocrlf=input,这样我就可以修复任何错误提交的文件,只需再次添加它们即可提交。我提供了一个提交文本:“修复错误提交的文件”。

至于.gitattributes。我不指望它,因为有更多的ui客户端不理解它。我只使用它来为文本和二进制文件提供提示,并可能标记一些异常文件,这些文件应该在任何地方保持相同的行尾:

*.java          text !eol # Don't do auto-detection. Treat as text (don't set any eol rule. use client's)
*.jpg           -text     # Don't do auto-detection. Treat as binary
*.sh            text eol=lf # Don't do auto-detection. Treat as text. Checkout and add with eol=lf
*.bat           text eol=crlf # Treat as text. Checkout and add with eol=crlf

问:但是我们为什么对换行处理策略感兴趣呢?

为了避免使用单字母更改提交,显示为5000行更改,只是因为执行更改的客户端在添加提交之前自动将整个文件从crlf转换为lf(或相反)。当涉及解决冲突时,这个可以是而痛苦。或者在某些情况下,它可能是不合理冲突的原因。


——更新2——

git客户端的错误在大多数情况下都可以工作。即使你只有windows客户端,linux客户端或者两者都有。这些都是:

  • 窗口: core.autocrlf=true表示签出时将行转换为CRLF,添加文件时将行转换为LF。
  • linux: core.autocrlf=input表示签出时不转换行(不需要,因为文件预计将使用LF提交),并在添加文件时将行转换为LF(如果需要)。 (——update3——:似乎默认是false,但同样是好的)

该属性可以在不同的作用域中设置。我建议显式地设置在--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

我也会强烈使用在windows上 git config --global core.autocrlf false(如果你只有windows客户端)与提议的相反 git文档 阻碍。设置为false将在repo中使用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客户端上只有在./configure中使用--with-libpcre编译)。
  • 如果执行上述命令发现了此类文件,请进行修改。这包括(至少在linux上):
    • 设置core.autocrlf=input (——更新3——)
    • 更改文件
    • 恢复更改(文件仍然显示为更改后的状态)
    • 提交它
  • 只使用最少的.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

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

  • -text(例如*.zip*.jpg文件:不会被视为文本。因此不会尝试行结束转换。Diff可能通过转换程序实现)
  • text !eol(例如,对于*.java*.html:作为文本处理,但未设置eol样式首选项。所以使用客户端设置。)
  • -text -diff -merge(例如*.hugefile:不作为文本处理。没有差异/合并可能)

——之前的更新——

一个会错误提交文件的客户端痛苦的例子:

netbeans 8.2(在windows上),将错误地提交所有文本文件crlf,除非,你有显式地设置core.autocrlf为全局。这与标准的git客户端行为相矛盾,并在稍后更新/合并时导致许多问题。这就是为什么一些文件显示不同(尽管他们不是)即使你还原了
即使你在项目中添加了正确的.gitattributes,在netbeans中也会发生相同的行为

在提交后使用以下命令,至少可以帮助您早期检测git回购是否有行结束问题

我花了几个小时来想出.gitattributes的最佳使用方法,最终意识到,我不能指望它。
不幸的是,只要存在基于jgit的编辑器(它不能正确处理.gitattributes),安全的解决方案是在任何地方强制LF,甚至在编辑器级别

使用下列anti-CRLF消毒剂。