行结束转换如何在不同操作系统之间与git core.autocrlf一起使用

时间:2010-07-08 18:39:40

标签: git newline core.autocrlf

我在Stack Overflow上阅读了很多不同的问题和答案,以及关于 core.autocrlf 设置如何工作的 git 文档。

这是我对以下内容的理解:

Unix和Mac OSX(OSX之前使用CR)客户端使用LF行结尾 Windows客户端使用CRLF行结尾。

当客户端上的core.autocrlf设置为true时,git存储库始终以LF行结束格式存储文件,客户端上文件中的行结尾在客户端(即Windows)的check out / commit上来回转换使用非LF行结尾,无论行结尾文件在客户端上的格式是什么(这与Tim Clem的定义不一致 - 请参阅下面的更新)。

这是一个矩阵,它试图为带有问号的core.autocrlf的'input'和'false'设置记录相同的内容,其中我不确定行结束转换行为。

我的问题是:

  1. 问题应该是什么?
  2. 此矩阵对“非问号”是否正确?
  3. 我会从答案中更新问号,因为似乎已形成共识。

                           core.autocrlf value
                true            input              false
    ----------------------------------------------------------
    commit   |  convert           ?                  ?
    new      |  to LF      (convert to LF?)   (no conversion?)
    
    commit   |  convert to        ?                 no 
    existing |  LF         (convert to LF?)     conversion
    
    checkout |  convert to        ?                 no
    existing |  CRLF       (no conversion?)     conversion
    
    

    我并不是真的在寻找各种设置的利弊意见。我只是在寻找数据,这清楚地说明了如何期望git能够在三种设置中运行。

    -

    2012年4月17日更新:在评论中阅读了JJD关联的the article by Tim Clem后,我修改了上表中“未知”值中的一些值,如以及更改“checkout existing | true转换为CRLF而不是转换为客户端”。以下是他给出的定义,这些定义比我在其他地方看到的更清楚:

    core.autocrlf = false

      

    这是默认设置,但我们鼓励大多数人更改此设置   立即。使用false的结果是Git不会混乱   在您的文件上有行结尾。您可以使用LF或CRLF签入文件   或CR或那些随机混合的那三个和Git并不关心。这个   可以使差异难以阅读和合并更困难。大多数人   在Unix / Linux世界中工作使用此值是因为它们没有   CRLF问题,他们不需要Git随时做额外的工作   文件被写入对象数据库或写入   工作目录。

    core.autocrlf = true

      

    这意味着Git将处理所有文本文件并确保这一点   将该文件写入对象数据库时,CRLF将替换为LF   在写入工作时将所有LF转回CRLF   目录。这是Windows上的推荐设置,因为它   确保您的存储库可以在其他平台上使用   将CRLF保留在工作目录中。

    core.autocrlf =输入

      

    这意味着Git将处理所有文本文件并确保这一点   将该文件写入对象时,CRLF将替换为LF   数据库。但是,它不会反过来。当你阅读文件   退出对象数据库并将其写入工作状态   目录中他们仍然会有LF来表示行尾。这个   设置通常用于Unix / Linux / OS X以防止CRLF   写入存储库。想法是,如果你粘贴   来自网络浏览器的代码,并意外地将CRLF纳入您的一个   文件,Git会确保你写的时候用LF替换它们   到对象数据库。

    Tim的文章很棒,我唯一能想到的就是缺少的是他认为存储库是LF格式的,这不一定是真的,特别是对于仅限Windows的项目。

    将Tim的文章与jmlane迄今为止最高投票答案进行比较,表明他们对真实和输入设置以及对错误设置的不同意见达成了完美的一致。

8 个答案:

答案 0 :(得分:116)

有关core.autocrlf工作原理的最佳说明,请参见gitattributes手册页,text属性部分。

这就是core.autocrlf目前的工作方式(至少从我所知道的v1.7.2开始):

  • core.autocrlf = true
    1. 从存储库中签出的只有LF个字符的文本文件在工作树中被标准化为CRLF;不会触及存储库中包含CRLF的文件
    2. 存储库中只有LF个字符的文本文件在提交回存储库时会从CRLF标准化为LF。存储库中包含CRLF的文件将不受影响。
  • core.autocrlf = input
    1. 从存储库中签出的文本文件将保留工作树中的原始EOL字符。
    2. 工作树中带有CRLF字符的文本文件在提交回存储库时会标准化为LF
  • core.autocrlf = false
    1. core.eol指示工作树的文本文件中的EOL字符。
    2. 默认情况下为
    3. core.eol = native,这意味着Windows EOL为CRLF,* nix EOL在工作树中为LF
    4. 存储库gitattributes设置确定提交到存储库的EOL字符规范化(默认为规范化为LF个字符。)

我刚才刚刚研究过这个问题,我也发现情况非常复杂。 core.eol设置肯定有助于阐明git如何处理EOL字符。

答案 1 :(得分:55)

混合平台项目中的EOL问题长期以来一直让我的生活变得悲惨。当回购中已存在具有不同且混合的EOL 的文件时,通常会出现问题。这意味着:

  1. 回购可能包含具有不同EOL的不同文件
  2. 回购中的某些文件可能具有混合EOL,例如CRLFLF在同一文件中的组合。
  3. 这种情况如何发生不是问题,但它确实发生了。

    我在Windows上针对各种模式及其组合运行了一些转换测试 这是我得到的,在一个稍微修改过的表中:

                     | Resulting conversion when       | Resulting conversion when 
                     | committing files with various   | checking out FROM repo - 
                     | EOLs INTO repo and              | with mixed files in it and
                     |  core.autocrlf value:           | core.autocrlf value:           
    --------------------------------------------------------------------------------
    File             | true       | input      | false | true       | input | false
    --------------------------------------------------------------------------------
    Windows-CRLF     | CRLF -> LF | CRLF -> LF | as-is | as-is      | as-is | as-is
    Unix -LF         | as-is      | as-is      | as-is | LF -> CRLF | as-is | as-is
    Mac  -CR         | as-is      | as-is      | as-is | as-is      | as-is | as-is
    Mixed-CRLF+LF    | as-is      | as-is      | as-is | as-is      | as-is | as-is
    Mixed-CRLF+LF+CR | as-is      | as-is      | as-is | as-is      | as-is | as-is
    
    

    如您所见,有两种情况在提交时发生转换(左侧列为3列)。在其余情况下,文件按原样提交。

    结帐时(右列3列),只有1例在以下情况下发生转换:

    1. core.autocrlftrue
    2. repo中的文件具有LF EOL。
    3. 对我来说最令人惊讶的是,我怀疑,许多EOL问题的原因是没有配置使CRLF + LF之类的混合EOL得到规范化。

      另请注意CR的“旧”Mac EOL也永远不会被转换 这意味着,如果写得不好的EOL转换脚本尝试使用CRLF s + LF s转换混合结束文件,只需将LF转换为CRLF s,那么将CR转换为CRLF的任何地方都会将文件保留为“孤独”CRCRLF的混合模式。
      然后,即使在true模式下,Git也不会转换任何内容,并且EOL将继续进行破坏。这实际上发生在我身上并且使我的文件搞得很糟糕,因为一些编辑和编译器(例如VS2010)不喜欢Mac EOL。

      我想真正解决这些问题的唯一方法是偶尔通过检查inputfalse模式下的所有文件来规范化整个仓库,运行正确的规范化并重新提交已更改的文件(如果有)。在Windows上,可能会继续使用core.autocrlf true

答案 2 :(得分:37)

使用upcoming Git 1.7.2

,“eol转换”方面即将发生变化

新的配置设置core.eol is being added/evolved

  

这是{Add} core.eol“配置变量”提交的替代品,该提交目前位于pu(我系列中的最后一个)。
  而不是暗示“core.autocrlf=true”替代“* text=auto”,它明确表明autocrlf仅适用于想要与之合作的用户   CRLF位于没有文本的存储库的工作目录中   文件规范化
  启用后,将忽略“core.eol”。

     

引入一个新的配置变量“core.eol”,允许用户设置哪些行结尾用于工作目录中的行末端规范化文件。
  它默认为“native”,这意味着Windows上的CRLF和其他地方的LF。   请注意,“core.autocrlf”会覆盖core.eol   这意味着:

[core]
  autocrlf = true
     即使core.eol设置为“lf”,

也会将CRLF放入工作目录。

core.eol:
     

设置要在工作目录中使用设置了text属性的文件的行结束类型   替代品是'lf','crlf'和'native',它们使用平台的原生行结尾   默认值为native


其他进化are being considered

  

对于1.8,我会考虑让core.autocrlf打开规范化并将工作目录行结束决定留给core.eol,但打破人们的设置。


git 2。8(2016年3月)改进了core.autocrlf影响eol的方式:

请参阅commit 817a0c7(2016年2月23日),commit 6e336a5commit df747b8commit df747b8(2016年2月10日),commit df747b8commit df747b8( 2016年2月10日),commit 4b4024fcommit bb211b4commit 92cce13commit 320d39ccommit 4b4024fcommit bb211b4commit 92cce13,{{ 3}}(2016年2月5日)commit 320d39c (由Torsten Bögershausen (tboegi)合并于Junio C Hamano -- gitster --,2016年2月26日)

  

convert.c:重构crlf_action

     

重构crlf_action的确定和用法   今天,如果文件中未设置“crlf”属性,则crlf_action设置为   CRLF_GUESS。请改用CRLF_UNDEFINED,并像以前一样搜索“text”或“eol”。

     

替换旧的CRLF_GUESS用法:

CRLF_GUESS && core.autocrlf=true -> CRLF_AUTO_CRLF
CRLF_GUESS && core.autocrlf=false -> CRLF_BINARY
CRLF_GUESS && core.autocrlf=input -> CRLF_AUTO_INPUT
  

通过定义:

,更清楚,更清楚,是什么
- CRLF_UNDEFINED : No attributes set. Temparally used, until core.autocrlf
                   and core.eol is evaluated and one of CRLF_BINARY,
                   CRLF_AUTO_INPUT or CRLF_AUTO_CRLF is selected
- CRLF_BINARY    : No processing of line endings.
- CRLF_TEXT      : attribute "text" is set, line endings are processed.
- CRLF_TEXT_INPUT: attribute "input" or "eol=lf" is set. This implies text.
- CRLF_TEXT_CRLF : attribute "eol=crlf" is set. This implies text.
- CRLF_AUTO      : attribute "auto" is set.
- CRLF_AUTO_INPUT: core.autocrlf=input (no attributes)
- CRLF_AUTO_CRLF : core.autocrlf=true  (no attributes)

由于commit c6b94eb添加torek

  

所有这些翻译(来自eol=autocrlf设置的任何EOL转换,以及“clean”过滤器)在文件从工作树移动到索引时运行,即在git add期间,而不是git commit时间   (请注意,git commit -a--only--include确实会在当时向索引添加文件。)

有关详情,请参阅“in the comments”。

答案 3 :(得分:27)

core.autocrlf值不依赖于操作系统类型,但在Windows上,默认值为true,对于Linux - input。我为提交和签出案例探索了3个可能的值,这是结果表:

╔═══════════════╦══════════════╦══════════════╦══════════════╗
║ core.autocrlf ║     false    ║     input    ║     true     ║
╠═══════════════╬══════════════╬══════════════╬══════════════╣
║               ║ LF   => LF   ║ LF   => LF   ║ LF   => LF   ║
║ git commit    ║ CR   => CR   ║ CR   => CR   ║ CR   => CR   ║
║               ║ CRLF => CRLF ║ CRLF => LF   ║ CRLF => LF   ║
╠═══════════════╬══════════════╬══════════════╬══════════════╣
║               ║ LF   => LF   ║ LF   => LF   ║ LF   => CRLF ║
║ git checkout  ║ CR   => CR   ║ CR   => CR   ║ CR   => CR   ║
║               ║ CRLF => CRLF ║ CRLF => CRLF ║ CRLF => CRLF ║
╚═══════════════╩══════════════╩══════════════╩══════════════╝

答案 4 :(得分:6)

到目前为止,这是我对它的理解,以防有人帮助。

core.autocrlf=truecore.safecrlf = true

您有一个存储库,其中所有行结尾都相同,但您在不同的平台上工作。 Git将确保您的行结尾转换为您的平台的默认值。为什么这很重要?假设您创建了一个新文件。平台上的文本编辑器将使用其默认行结尾。当您检入它时,如果您没有将core.autocrlf设置为true,那么您为平台上的某个人默认为不同的行结尾引入了行结尾不一致。我总是设置safecrlf,因为我想知道crlf操作是可逆的。使用这两个设置, git正在修改您的文件,但它会验证修改是否可逆

core.autocrlf=false

您的存储库已经签入了混合行结尾,并且修复错误的行结尾可能会破坏其他内容。在这种情况下,最好不要告诉git转换行结尾,因为这样会加剧它设计解决的问题 - 使diff更容易阅读和合并更少的痛苦。使用此设置, git不会修改您的文件

core.autocrlf=input

我不使用它,因为这样做的原因是为了覆盖一个用例,你在默认为LF行结尾的平台上创建了一个CRLF行结尾的文件。我更喜欢让我的文本编辑器始终保存平台的行结束默认值的新文件。

答案 5 :(得分:2)

在linux和windows上都进行了一些测试。我使用的测试文件包含以LF结尾的行以及以CRLF结尾的行 文件已提交,删除,然后签出。 core.autocrlf的值在commit之前设置,也在checkout之前设置。 结果如下。

commit core.autocrlf false, remove, checkout core.autocrlf false: LF=>LF   CRLF=>CRLF  
commit core.autocrlf false, remove, checkout core.autocrlf input: LF=>LF   CRLF=>CRLF  
commit core.autocrlf false, remove, checkout core.autocrlf true : LF=>LF   CRLF=>CRLF  
commit core.autocrlf input, remove, checkout core.autocrlf false: LF=>LF   CRLF=>LF  
commit core.autocrlf input, remove, checkout core.autocrlf input: LF=>LF   CRLF=>LF  
commit core.autocrlf input, remove, checkout core.autocrlf true : LF=>CRLF CRLF=>CRLF  
commit core.autocrlf true, remove, checkout core.autocrlf false: LF=>LF   CRLF=>LF  
commit core.autocrlf true, remove, checkout core.autocrlf input: LF=>LF   CRLF=>LF  
commit core.autocrlf true,  remove, checkout core.autocrlf true : LF=>CRLF CRLF=>CRLF  

答案 6 :(得分:1)

不,@ jmlane的答案是错误的。

对于Checkin (git add, git commit)

  1. 如果text属性为Set, Set value to 'auto',则转换发生在文件已使用'CRLF'提交
  2. 如果text属性为Unset:没有任何反应,请Checkout
  3. 如果text属性为Unspecified,则转化取决于core.autocrlf
    1. 如果autocrlf = input or autocrlf = true,转换只发生在存储库中的文件是'LF'时,如果它是'CRLF',则不会发生任何事情。
    2. if autocrlf = false,没有任何反应
  4. 对于Checkout

    1. 如果text属性为Unset:没有任何反应。
    2. 如果text属性为Set, Set value to 'auto:则取决于core.autocrlfcore.eol
      1. core.autocrlf =输入:没有任何反应
      2. core.autocrlf = true:转换仅在存储库中的文件为“LF”,“LF” - >时发生。 'CRLF'
      3. core.autocrlf = false:转换仅在存储库中的文件为“LF”,“LF” - >时发生。 core.eol
    3. 如果text属性为Unspecified,则取决于core.autocrlf
      1. 2.1
      2. 相同
      3. 2.2
      4. 相同
      5. 没有,没有任何反应,当text属性为Unspecified
      6. 时,core.eol无效
    4. 默认行为

      因此默认行为是text属性Unspecifiedcore.autocrlf = false

      1. 进行检查,没有任何反应
      2. 结账,没有任何反应
      3. 结论

        1. 如果设置了text属性,则签入行为取决于自身,而不是取决于autocrlf
        2. autocrlf或core.eol用于结帐行为,autocrlf> core.eol

答案 7 :(得分:0)

LMAO!

你们都搞错了。

在提交时导致 CRLF->LF 的语句 core.autocrlftrue 是明显错误的!
没那么简单,你看...
(该设置对应于 text=auto 中的 .gitattributes 和 git config 中的 core.eol 设置为 crlf;究竟是什么意思?哈哈哈。)
这意味着(如果文件没有设置 .gitattributes 文本属性,则 core.autocrlftrue,意味着)它取决于它是否是正在提交的新文件(在这种情况下,是的,它将在 git repo 数据库中标准化为 LF),或者它是否是您编辑和提交的现有文件(在这种情况下不会发生任何事情;除非 --hahaha-- 您在其中运行 git add --renormalize .在这种情况下,它将在 git repo 数据库中标准化)。

但老实说:谁在乎?

(你看...上面的机制,只发生在一个文件中,.gitattributes没有放置了一个文本属性的变体:text-texttext=auto。)

您真的应该在所有文件中使用带有默认设置的 .gitattributes,或者

* -text
# followed by specialization

默认所有(特化除外)原样并完全覆盖 core.autocrlf, 或使用默认值

*  text=auto
# followed by specialization

意味着git自动检测为非二进制(文本)的所有文件(除了专业),在git数据库[1**]中有LF,当core.autocrlftrue时获得CRLF或者当 core.eolcrlf 时,或者当 core.eolnative(默认)并且您使用的是 Windows 平台时。否则你会得到 LF。

我的意思是什么专业?例如,.bat 文件为 CRLF,.sh 文件为 LF,通过以下任一方式:

*.sh           text eol=lf

# *.bat
*.[bB][aA][tT] text eol=crlf

# *.sh are committed correctly as-is (LF)
*.sh           -text

# *.bat are committed correctly as-is (CRLF)
*.[bB][aA][tT] -text

但是是的……事情并没有那么简单。哈哈。

[1**]:对于与 text=auto attribute 匹配的所有文件(即没有其他专业化),情况就是这样,因为我认为当 .gitattribute 为将创建