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

Mic*_*dox 208 git newline core.autocrlf

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

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

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

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

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

我的问题是:

  1. 问号应该是什么?
  2. 这个矩阵对"非问号"是否正确?

我将从答案中更新问号,因为似乎已形成共识.

                       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在评论中链接的Tim Clem的文章后,我修改了上表中"未知"值中的一些值,并更改了"checkout existing | true to conversion"到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写入存储库.我们的想法是,如果您从Web浏览器粘贴代码并意外地将CRLF放入您的某个文件中,Git会确保在您写入对象数据库时将它们替换为LF.

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

将Tim的文章与jmlane迄今为止最高投票答案进行比较,可以看出真实和输入设置的完美一致以及对错误设置的不同意见.

jml*_*ane 122

有关如何core.autocrlf工作的最佳解释可在gitattributes手册页的text属性部分中找到.

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

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

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

  • 对于autocrlf = true不应该是以下?在存储库中仅具有CRLF EOL字符的文本文件在提交回存储库时从CRLF规范化为LF.存储库中包含LF的文件将保持不变. (3认同)
  • 对我来说,即使autocrlf = false,git也会将EOL转换为CRLF.看完这个答案后,我意识到我的.gitattribute文件有text = auto设置,这导致了麻烦. (2认同)
  • `.gitattributes` 文件不应该优先于 `core.autocrlf` 设置吗? (2认同)

Adi*_*vit 61

混合平台项目中的EOL问题长期以来让我的生活变得悲惨.当有不同的和混合EOLS已经文件通常出现的问题已经在回购协议.这意味着:

  1. 回购可能具有不同EOL的不同文件
  2. 回购中的某些文件可能具有混合EOL,例如同一文件的组合CRLFLF.

如何发生这种情况不是问题,但确实发生了.

我在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中的文件具有LFEOL.

最令人惊讶的对我来说,我怀疑,很多EOL问题的原因是没有配置,其中混合EOL喜欢CRLF+ LF得到规范化.

另请注意,"旧"Mac EOL也CR只是永远不会被转换.
这意味着如果编写错误的EOL转换脚本尝试使用CRLFs + LFs 转换混合结束文件,只需将LFs 转换为CRLFs,那么CR无论CRLF转换为何处,它都会使文件处于混合模式,并且具有"孤独" CRCRLF.
然后,即使在true模式下,Git也不会转换任何东西,并且EOL将继续破坏.这实际上发生在我身上,并且我的文件非常糟糕,因为一些编辑器和编译器(例如VS2010)不喜欢Mac EOL.

我想真正处理这些问题的唯一方法是偶尔通过检查所有文件inputfalse模式,运行适当的规范化并重新提交已更改的文件(如果有的话)来规范化整个存储库.在Windows上,大概可以继续使用core.autocrlf true.

  • 很好的答案,但我不能同意的一句话是_On Windows,大概是恢复使用`core.autocrlf true`_.我个人认为应该始终使用`input`. (4认同)

Von*_*onC 39

随着即将推出的Git 1.7.2,"eol转换"方面即将发生变化:

core.eol正在添加/演进新的配置设置:

这是当前的"添加" 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
Run Code Online (Sandbox Code Playgroud)

即使core.eol设置为" lf",CRLF也会放在工作目录中.

core.eol:
Run Code Online (Sandbox Code Playgroud)

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


正在考虑其他演变:

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


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

请参阅commit 817a0c7(2016年2月23日),commit 6e336a5,commit df747b8,commit df747b8(2016年2月10日),commit df747b8,commit df747b8(2016年2月10日),并提交4b4024f,commit bb211b4,commit 92cce13,commit 320d39c,commit 4b4024f,提交bb211b4,提交92cce13,提交320d39c由(2016年2月5日)的TorstenBögershausen( )tboegi.
(由Junio C gitsterHamano合并- -提交c6b94eb中,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
Run Code Online (Sandbox Code Playgroud)

通过定义:更清楚,更清楚,是什么

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

作为托雷克增加的评论:

所有这些翻译(来自eol=autocrlf设置的任何EOL转换,以及" clean"过滤器)在文件从工作树移动到索引时运行,即在期间git add而不是在git commit时间.
(注意,git commit -a或者--only或者--include在那时将文件添加到索引中.)

有关详细信息,请参阅" autocrlf和eol之间的区别 ".

  • 不幸的是,这并没有为我增加清晰度.看起来他们说当前的实施存在问题(目前尚不清楚这些问题是什么),并且他们正在增加解决这些未指明问题的努力的复杂性.在我看来,core.autocrlf设置已经过于复杂并且记录不足,而且情况似乎越来越糟.再次感谢您的提醒. (18认同)
  • 这似乎不是一个令人满意的解决方案,并且似乎与 core.autocrlf 具有相同的问题。我的偏好是 git 永远不会自动修改任何内容,但它会警告想要添加或提交错误行结尾的用户。因此,您需要一个命令行选项来允许“git add”添加“错误”的行结尾。(可能 git add 是比 git commit 更好的检查位置) (2认同)
  • @donquixote:我意识到这已经很老了,但我现在才读到你的评论。事实上,所有这些转换(从 eol= 或 autocrlf 设置的任何 EOL 转换,*和*“干净”过滤器)都是在文件从工作树移动到索引时运行,即在“git add”期间而不是在“git commit”期间运行` 时间。(请注意,`git commit -a` 或 `--only` 或 `--include` 确实会在那时将文件添加到索引中。)就其价值而言,你、我和 Linus Torvalds 都讨厌这个想法VCS *永远*修改正在提交的内容。但还有所有这些 Windows 用户...:-) (2认同)

pra*_*att 32

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 ?
??????????????????????????????????????????????????????????????
Run Code Online (Sandbox Code Playgroud)

  • 简短的文字总结:永远不会碰到带有CR的文件。false永远不会碰到行尾。true总是提交为LF,而签出为CRLF。而input总是以LF的形式提交并按原样签出。 (2认同)

Car*_*arl 7

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

core.autocrlf=truecore.safecrlf = true

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

core.autocrlf=false

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

core.autocrlf=input

我不使用它,因为其原因是为了覆盖一个用例,在该用例中,您创建了一个在默认为LF行结尾的平台上具有CRLF行结尾的文件.我更喜欢让我的文本编辑器始终使用平台的行结束默认值保存新文件.


Vic*_*iOs 6

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

为了Checkin (git add, git commit)

  1. 如果text属性为Set, Set value to 'auto',则转换发生且文件已使用“CRLF”提交
  2. 如果text属性是Unset:什么也没发生,则 enen 为Checkout
  3. 如果text属性为Unspecified,则转换取决于core.autocrlf
    1. if autocrlf = input or autocrlf = true,仅当存储库中的文件为“LF”时才会发生转换,如果已为“CRLF”,则不会发生任何情况。
    2. 如果autocrlf = false,什么也没有发生

为了Checkout

  1. 如果text属性是Unset:什么也不会发生。
  2. 如果text属性是Set, Set value to 'auto:则取决于core.autocrlf, core.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. 2.2
    3. text无,没有任何反应,当属性为时core.eol 无效Unspecified

默认行为

所以默认行为是text属性是Unspecifiedand core.autocrlf = false

  1. 办理登机手续时,没有任何反应
  2. 结帐时,没有任何反应

结论

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