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


220

我已经阅读了关于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值
            真输入假
-------------------------------------------------- --------
提交| 兑换 ??
新 转换为LF(转换为LF?)(不转换?)

提交| 转换成 ?没有
现有 LF(转换为LF?)转换

结帐| 转换成 ?没有
现有 CRLF(无转换?)转换

我并不是真的在寻求有关各种设置的优缺点的意见。我只是在寻找可以使git如何在这三个设置中运行的数据清楚。

-

更新04/17/2012:在阅读 JJD链接的Tim Clem的文章后,我修改了上表中“未知”值中的某些值,以及更改了“ checkout existing | true”以进行转换而不是转换为客户端”。这是他给出的定义,这些定义比我在其他地方看到的任何定义都更清楚:

core.autocrlf =假

这是默认设置,但建议大多数人立即更改此设置。使用false的结果是Git永远不会弄乱文件的行尾。您可以使用LF或CRLF或CR或这三者的某种随机组合来检入文件,而Git不在乎。这会使差异变得难以阅读,合并变得更加困难。在Unix / Linux世界中工作的大多数人都使用此值,因为他们没有CRLF问题,并且无论何时将文件写入对象数据库或写入工作目录中,都不需要Git进行额外的工作。

core.autocrlf =真

这意味着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项目而言。

jmlane将Tim的文章与迄今为止获得最高投票的答案进行了比较,显示出对真实和输入设置的完全赞同,对错误设置的反对。


7
保持autocrlf);以虚假似乎容易得多stackoverflow.com/questions/2333424/...
VonC

@VonC:我已经读过了,我想我理解了,但是我不一定要做出选择。我使用git存储库,但我无法控制谁需要以某种方式设置值。
Michael Maddox

5
如果Windows也标准化为LF会不会很好?Mac曾经是CR(v10之前的版本),但现在已标准化为LF。
Brett Ryan

3
我需要添加指向蒂莫西·克莱姆Timothy Clem)精彩文章的链接-请阅读《注意线路的尽头》
JJD

1
场景:我是一名Linux / Windows分离开发人员。我只使用可以识别两种类型的行尾的文本编辑器(IE。vim,eclipse)。我只需要(想要)处理以LF结尾的文件。我目前在全局git配置中设置了core.autocrlf = input。我可以去吗?我会发生冲突吗?
克里斯(Chris)

Answers:


128

core.autocrlfgitattributes手册页的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字符。


3
for autocrlf = true不应为以下内容吗?在存储库中仅包含CRLF EOL字符的文本文件在提交回存储库时,将从CRLF标准化为LF。存储库中包含LF的文件将保持不变。
Piotr Lewandowski

2
对我来说,即使autocrlf = false git也在将EOL转换为CRLF。阅读此答案后,我意识到我的.gitattribute文件已设置了text = auto,这引起了麻烦。
irsis

1
对于core.autocrlf = false,如果我没有gitattributes文件,是否意味着将没有规范化?还是意味着它将使用默认规范化?
Chin

.gitattributes文件不应该优先于core.autocrlf设置吗?
Qwerty

63

长期以来,混合平台项目中的EOL问题一直困扰着我。当已经有不同的和混合EOLS文件通常出现的问题已经在回购协议。这意味着:

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

这种情况的发生不是这里的问题,而是确实发生了。

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

                 | 当| 在以下情况下产生转换
                 | 提交各种文件| 从回购中签出-
                 | EOLs回购和| 里面有混合文件
                 | core.autocrlf值:| core.autocrlf值:           
-------------------------------------------------- ------------------------------
档案| 真实| 输入| 错误 真实| 输入| 假
-------------------------------------------------- ------------------------------
Windows-CRLF | CRLF-> LF | CRLF-> LF | 原样| 原样| 原样| 原样
Unix -LF | 原样| 原样| 原样| LF-> CRLF | 原样| 原样
Mac -CR | 原样| 原样| 原样| 原样| 原样| 原样
混合CRLF + LF | 原样| 原样| 原样| 原样| 原样| 原样
混合CRLF + LF + CR | 原样| 原样| 原样| 原样| 原样| 原样

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

结帐时(右三列),只有以下一种情况会发生转换:

  1. core.autocrlftrue
  2. 存储库中的文件具有LFEOL。

对于我来说,最令人惊讶的是,我怀疑许多EOL问题的原因是没有像CRLF+ 这样的混合EOL LF被标准化的配置。

还要注意,也只有“旧的” Mac EOL CR永远也不会转换。
这意味着,如果编写不正确的EOL转换脚本试图通过仅将s 转换为s来转换带有CRLFs + LFs 的混合结尾文件,则无论a 转换为s,它将使文件处于带有“ lonely” s 的混合模式。 这样,即使在模式下,Git也不会转换任何内容,并且EOL破坏仍在继续。这实际上发生在我身上,并严重破坏了我的文件,因为某些编辑器和编译器(例如VS2010)不喜欢Mac EOL。LFCRLFCRCRLFCRCRLF
true

我猜想,真正解决这些问题的唯一方法是通过以或模式签出所有文件,运行适当的规范化并重新提交更改的文件(如果有)来偶尔对整个仓库进行规范化。在Windows上,大概可以继续使用。inputfalsecore.autocrlf true


4
很好的答案,但是我不能同意的一句话是在Windows上,大概可以继续使用core.autocrlf true。我个人认为input应该始终使用。
G. Demecki

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

即使将CRLF core.eol设置为“ lf”,也将其放置在工作目录中。

core.eol:

设置行尾类型以在工作目录中用于text设置了属性的文件。
备选方案是“ lf”,“ crlf”和“ native”,它们使用平台的本机行结尾。
默认值为native


正在考虑其他发展:

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


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

提交817a0c7(2016年2月23日),提交6e336a5提交df747b8提交df747b8(2016年2月10日),提交df747b8提交df747b8(2016年2月10日),以及提交4b4024f提交bb211b4提交92cce13提交320d39c提交4b4024f提交bb211b4提交92cce13提交320d39c(2016年2月5日),作者是TorstenBögershausen(tboegi
(由Junio C gitsterHamano合并--commit 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

通过定义以下内容来更清楚地说明什么是什么:

- 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)

正如torek 在评论中添加的那样

当文件从工作树移动到索引时(即,而不是在时间上),将运行所有这些转换(来自eol=autocrlf设置的任何EOL转换以及“ clean”过滤器)。 (但是请注意,还是在那个时候将or 添加到索引中。)git addgit commit
git commit -a--only--include

有关更多信息,请参见“ autocrlf和eol有什么区别 ”。


18
不幸的是,这对我来说并没有增加清晰度。似乎他们是在说当前的实现存在问题(不清楚这些问题是什么),并且他们正在增加复杂性以解决这些未说明的问题。在我看来,core.autocrlf设置已经过于复杂且文档不足,而且这种情况似乎越来越严重。再次感谢您的注意。
Michael Maddox 2010年

1
这似乎不是令人满意的解决方案,并且似乎具有与core.autocrlf相同的问题。我的偏好是git永远不会自动修改任何内容,但是会警告想要添加或提交错误行尾的用户。因此,您将需要一个命令行选项来允许“ git add”添加“错误的”行尾。(可能是git add比git commit更好。)
donquixote 2014年

这将迫使各个用户更改其编辑器设置,并真正解决问题。虽然这将允许保留来自第三方或已签入存储库的文件的“错误”行结尾。
donquixote

再次@donquixote,我同意。但是,core.eol仅关于“自动修改”您在文件中明确声明的内容.gitattributes。这与core.autocrlf适用于仓库中的任何文件不同。这是一个声明性过程。
VonC 2014年

1
@donquixote:我知道这已经很老了,但是我现在只读你的评论。实际上,所有这些转换(从eol =或autocrlf设置进行的任何EOL转换,以及 “纯净”过滤器)都是在文件从工作树移动到索引时(即,git add而不是在git commit时间上)运行的。(请注意,git commit -a或者--only--include做文件添加到当时的指数,虽然)。对于它的价值,你和我和Linus Torvalds的所有讨厌的VCS的想法不断改变什么东西被提交。但是,所有这些Windows用户... :-)
torek '17

34

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 ║
╚═══════════════╩══════════════╩══════════════╩══════════════╝

5
简短的文字总结:CR永不碰触的文件。false永远不要碰到行尾。true始终以提交,LF并以签出CRLF。并input始终按原样提交LF并签出。
Furkan Kambay

7

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

core.autocrlf=truecore.safecrlf = true

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

core.autocrlf=false

您的存储库中已签入混合的行尾,并且修复不正确的行尾可能会破坏其他内容。在这种情况下,最好不要告诉git转换行尾,因为这样会加剧原本打算解决的问题-使diff易于阅读,并且合并起来不那么痛苦。使用此设置,git不会修改您的文件

core.autocrlf=input

我不使用它,因为这样做的原因是为了涵盖一个用例,其中您在默认为LF行尾的平台上创建了具有CRLF行尾的文件。相反,我更希望使文本编辑器始终使用平台行尾默认值保存新文件。


3

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

对于Checkin (git add, git commit)

  1. 如果textproperty为Set, Set value to 'auto',则转换将在使用'CRLF'提交文件后进行
  2. 如果text属性是Unset:什么都没有发生,请enenCheckout
  3. 如果textproperty是Unspecified,则转换取决于core.autocrlf
    1. 如果为autocrlf = input or autocrlf = true,则仅当存储库中的文件为“ LF”时才进行转换,如果为“ CRLF”,则不会发生任何转换。
    2. 如果autocrlf = false没有任何反应

对于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. 与...相同 2.2
    3. 没有,什么也没有发生,当textproperty 为时,core.eol无效Unspecified

默认行为

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

  1. 办理登机手续,没有任何反应
  2. 结帐时,什么也没发生

结论

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

2

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

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  
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.