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

时间:2008-10-04 20:39:28

标签: git cross-platform newline eol

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

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

每个答案请分享一个最佳做法。

9 个答案:

答案 0 :(得分:712)

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

请参阅 github:help 指南中的详细信息 Dealing with line endings

  

Git允许您设置a的行结束属性   直接使用中的text attribute进行回购    .gitattributes 文件。此文件已提交到   回购并覆盖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

最流行的编程语言有一个方便的collection of ready to use .gitattributes files。让你开始是有用的。

创建或调整 .gitattributes 后,您应该执行一次换取line endings re-normalization

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

最后,Mind the End of 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用于许多用例的工具。

谁说软件很简单? : - /

答案 1 :(得分:111)

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

答案 2 :(得分:80)

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

以下一些其他背景信息:

  

如果你愿意,它应该是core.autocrlf=true   如果您愿意,DOS结束或core.autocrlf=input   UNIX的换行。在这两种情况下,您的Git存储库都将   只有LF,这是正确的事情。唯一的   core.autocrlf=false的参数是自动的   启发式可能会错误地将某些二进制文件检测为   然后你的瓷砖将被破坏。所以,   引入了core.safecrlf选项以警告用户是否   发生了不可逆转的变化。实际上,有两个   不可逆转的变化的可能性 - 混合   在文本文件中以行结尾,在此规范化中   希望,所以这个警告可以忽略,或   (非常不可能)Git错误地检测到了你的   二进制文件作为文本。然后你需要使用属性   告诉Git这个文件是二进制文件。

以上段落最初是从gmane.org上的一个帖子中删除的,但它已经失效了。

答案 3 :(得分:57)

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

甲。全球per All Repositories Setup

1)转换all to one format

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中。或per Repository Setup

1)转换all to one format

find . -type f -not -path "./.git/*" -exec dos2unix {} \;
git commit -a -m 'dos2unix conversion'

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

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

不要担心你的二进制文件--Git应该对它们足够聪明。


More about safecrlf/autocrlf variables

答案 4 :(得分:10)

尝试将core.autocrlf配置选项设置为true。另请查看core.safecrlf选项。

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

  

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

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

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

答案 5 :(得分:9)

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

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

20多年后,我们仍在处理操作系统之间的行结束差异......悲伤。

答案 6 :(得分:7)

这些是与 Mac Linux 用户共享代码的 Windows Visual Studio 用户的两个选项。有关扩展说明,请阅读gitattributes manual

* text = auto

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

*   text=auto

这会规范化回购邮件中LF行结尾的所有文件。

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

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

示例:

Hello\r\nWorld

将在回购中标准化为:

Hello\nWorld

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

Hello\r\nWorld

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

Hello\nWorld
  

注意:如果您的repo已包含未规范化的文件,git status将在下次对其进行任何更改时将这些文件显示为已完全修改,以及其他用户稍后合并其更改可能会很麻烦。有关详细信息,请参阅refreshing a repository after changing line endings

core.autocrlf = true

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

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

  • 只有将文件标准化为LF行结尾,只有在将添加到回购时。如果存储库中没有标准化的文件,则此设置不会触及它们。
  • 所有文本文件都将转换为工作目录中的CRLF行结尾。

这种方法的问题在于:

  • 如果您是autocrlf = input的Windows用户,您会看到一堆行LF行的文件。对团队的其他成员而言并不构成危险,因为您的提交仍将使用LF行结尾进行规范化。
  • 如果您是使用core.autocrlf = false的Windows用户,您会看到一堆带有LF行结尾的文件,您可以将带有CRLF行结尾的文件引入回购邮件。
  • 大多数Mac用户使用autocrlf = input并且可能会获得CRLF个文件结尾的文件,可能是来自core.autocrlf = false的Windows用户。

答案 7 :(得分:4)

这只是解决方法解决方案:

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

在我的案例中,有> 10名程序员在Windows中开发项目。该项目已通过CRLF签入,没有强制选择LF的选项。

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

我的解决方案:

<强> Windows的机器: 让一切都保持原样。什么都不关心,因为你是一个默认的Windows'孤狼'开发者,你必须像这样处理:“广阔的世界里没有其他系统,是吗?”

<强> Unix的机

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

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

    unix2dos $(git lc)
    
  3. 可选...

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

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

      ... | egrep -r "^(\?| ).*\.(txt|conf)" | ...
      
    3. 使用其他快捷方式随意使其更方便:

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

      ...并通过输入

      来解锁转换后的内容
      git c2dos
      

答案 8 :(得分:4)

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

<击>

使用以下anti-CRLF消毒剂。

---更新2 ---

git客户端的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

此外,我强烈劝阻使用git config --global core.autocrlf false(如果您只有Windows的客户端)与git documentation提议的内容形成鲜明对比。设置为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客户端在--with-libpcre中使用./configure
  • 如果通过执行上述命令找到任何此类文件,请更正它们。
  • 仅使用最低.gitattributes
  • 指示用户将上述core.autocrlf设置为默认值。
  • 不要对.gitattributes的存在计算100%。 IDE的git-clients可能会忽略它们或对它们进行不同的处理。

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

# Always checkout with LF
*.sh            text eol=lf
# Always checkout with CRLF
*.bat           text eol=crlf

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

  • -text(例如*.zip*.jpg个文件:不会被视为文本。因此不会尝试进行行结束转换。可能通过转换程序实现差异化<) / LI>
  • text !eol(例如*.java*.html:处理为文字,但未设置eol样式首选项。因此使用客户端设置。)
  • -text -diff -merge(例如*.hugefile:未被视为文字。无法进行差异/合并)

---上一次更新---

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

netbeans 8.2 (在Windows上)会错误地使用 CRLF提交所有文本文件,除非明确设置 {{ 1}}作为全球。这与标准的git客户端行为相矛盾,并且在更新/合并时会导致很多问题。这使得某些文件看起来不同(尽管它们不是),即使您还原
即使您已将正确的core.autocrlf添加到项目中,也会发生netbeans中的相同行为。

提交后使用以下命令,至少可以帮助您及早发现git repo是否存在行结尾问题:.gitattributes