如何在不同的操作系统之间使用git core.autocrlf来结束转换

我已经阅读了Stack Overflow的许多不同的问题和解答,以及有关core.autocrlf设置如何工作的git文档。

这是我从我读过的理解:

Unix和Mac OSX(pre-OSX使用CR)客户端使用LF行尾。
Windows客户端使用CRLF行尾。

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

这是一个matrix,试图loggingcore.autocrlf的“input”和“虚假”设置相同的问号,我不知道行结束转换行为。

我的问题是:

  1. 问号应该是什么?
  2. 这个matrix是否正确的“非问号”?

随着共识似乎形成,我会更新答案中的问号。

                        core.autocrlf值
            真正的input错误
 -------------------------------------------------- --------
提交| 兑换 ?  ?
新的| 到LF(转换为LF?)(没有转换?)

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

结账| 转换成 ? 没有
现有的|  CRLF(不转换?)转换

我并不是真的在各种设置的利弊上寻找意见。 我只是在寻找数据,这使得清楚如何期待混帐与三个设置的每一个操作。

2012年4月17日更新 :在阅读了由JJD链接的Tim Clem的文章之后,我修改了上表中“未知”值中的一些值,并更改了“checkout existing | true to convert到CRLF而不是转换为客户“。 以下是他给出的定义,比我在其他地方看到的更清楚:

core.autocrlf = false

这是默认的,但是大多数人被鼓励立即改变这一点。 使用false的结果是,Git不会混淆文件中的行结尾。 你可以用LF或CRLF或CR来检查文件,也可以用这三个文件的随机组合,而Git不关心。 这可以使差异更难以阅读和合并更困难。 大多数在Unix / Linux世界工作的人使用这个值,因为他们没有CRLF问题,并且当文件被写入对象数据库或写入工作目录时,他们不需要Git做额外的工作。

core.autocrlf = true

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

core.autocrlf =input

这意味着Git将处理所有的文本文件,并确保在将该文件写入对象数据库时,将CRLFreplace为LF。 但是,这不会做相反的事情。 当你从对象数据库中读取文件并将它们写入工作目录时,它们仍然有LF来表示行结束。 通常在Unix / Linux / OS X上使用此设置来防止CRLF写入存储库。 这个想法是,如果你从Web浏览器粘贴代码,并意外地将CRLFs放到你的文件中,那么当你写对象数据库的时候,Git会确保它们被LF代替。

Tim的文章非常好,我能想到的唯一的缺点是他认为版本库是LF格式,这不一定是真实的,特别是对于只有Windows的项目。

将Tim的文章与jmlane迄今为止投票最高的答案进行比较,表明了对错误设置的真实和input设置和不同意见的完美协议。

关于core.autocrlf如何工作的最好解释是在gitattributes手册页的text属性部分find的。

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

  • core.autocrlf = true
    1. 从存储库签出的只有LF EOL字符的文本文件在工作树中被标准化为CRLF ; 存储库中包含CRLF文件将不会被触及
    2. 在存储库中仅具有LF EOL字符的文本文件在提交回存储库时从CRLF归一化到LF 。 存储库中包含CRLF文件将保持不变。
  • core.autocrlf = input
    1. 从存储库检出的文本文件将保留工作树中的原始EOL字符。
    2. CRLF EOL字符的工作树中的文本文件在提交回存储库时被标准化为LF
  • core.autocrlf = false
    1. core.eol在工作树的文本文件中core.eol EOL字符。
    2. core.eol = native默认core.eol = native ,这意味着Windows EOL是CRLF而基于Unix的操作系统是工作树中的LF
    3. 存储库gitattributes设置确定提交到存储库的EOL字符规范化(默认是标准化为LF EOL字符)。

我刚才才研究这个问题,而且我也觉得这个情况非常复杂。 core.eol设置确实有助于阐明如何处理EOL字符。

混合平台项目中的EOL问题使我的生活长期处于悲惨境地。 这个问题通常出现在已经存在具有不同的和混合的EOL的文件中。 这意味着:

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

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

我在Windows上为各种模式及其组合进行了一些转换testing。
这是我得到的,在一个稍微修改的表格中:

                  | 在|时导致转换 导致转换时 
                  | 提交各种|的文件 退房从回购 -  
                  |  EOLs INTO回购和| 在它和混合文件
                  |  core.autocrlf值:|  core.autocrlf值:           
 -------------------------------------------------- ------------------------------
文件|  true | input|  false |  true | input| 假
 -------------------------------------------------- ------------------------------
 Windows-CRLF |  CRLF  - > LF |  CRLF  - > LF | 按原样| 按原样| 按原样| 按原样
 Unix -LF | 按原样| 按原样| 按原样|  LF  - > CRLF | 按原样| 按原样
 Mac -CR | 按原样| 按原样| 按原样| 按原样| 按原样| 按原样
混合CRLF + LF | 按原样| 按原样| 按原样| 按原样| 按原样| 按原样
 Mixed-CRLF + LF + CR | 按原样| 按原样| 按原样| 按原样| 按原样| 按原样

正如你所看到的,在提交时发生转换的情况有两种(左三列)。 在其余情况下,这些文件按原样提交。

在结帐时(右边3列),只有一种情况发生转换时:

  1. core.autocrlftrue
  2. 回购中的文件有LF EOL。

最令我惊讶的是,我怀疑,许多EOL问题的原因是没有像CRLF + LF这样的混合EOL得到规范化的configuration。

还要注意的是, CR “旧”Mac EOL也不会被转换。
这意味着如果一个写得不好的EOL转换脚本试图用CRLF s + LF s转换一个混合的结尾文件,只需要将LF s转换为CRLF s,那么它就会将文件保留在一个混合模式,带有“寂寞” CRLF被转换为CRCRLF
即使在true模式下,Git也不会转换任何东西,而EOL的浩劫仍在继续。 这实际上发生在我身上,并且糟糕透顶,因为一些编辑器和编译器(例如VS2010)不喜欢Mac EOL。

我想真正处理这些问题的唯一方法是偶尔通过检查inputfalse模式下的所有文件,运行适当的规范化并重新提交更改后的文件(如果有的话)来标准化整个回购。 在Windows上,大概恢复与core.autocrlf true工作。

即将到来的Git 1.7.2将会在“eol转换”方面发生变化:

一个新的configuration设置core.eol被添加/演变 :

这是replace“添加” core.eol “configurationvariables”提交目前在pu (我的系列中的最后一个)。
而不是暗示“ core.autocrlf=true ”是“ * text=auto ”的替代, 它明确表示autocrlf仅适用于那些想在CRLFs工作目录中工作的用户有文本文件规范化
当它被启用时,“core.eol”被忽略。

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

 [core] autocrlf = true 

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

 core.eol: 

设置text属性设置的文件在工作目录中使用的行结束types。
替代方法是“lf”,“crlf”和“native”,它们使用平台的本地行结尾。
默认值是native


正在考虑其他的演变:

对于1.8,我会考虑使core.autocrlf只是开启规范化,并将工作目录行的结尾决定为core.eol,但是这破坏人们的设置。


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

提交df747b8 (2016年2月10日), 提交df747b8 , 提交df747b8 (2016年2月10日), 提交4b4024f , 提交bb211b4 , 提交92cce13 , 提交320d39c , 提交4b4024f , 提交bc211b4 , 提交92cce13 , 提交320d39c (2016年2月5日)通过tboegitboegi ) 。
(合并由Junio C gitstergitster -在提交c6b94eb ,2016年2月26日)

convert.c :重构crlf_action

重构crlf_action的确定和使用。
今天,当文件上没有设置“ crlf ”属性时, crlf_action设置为CRLF_GUESS 。 改为使用CRLF_UNDEFINED ,然后像以前一样search“ text ”或“ eol ”。

replace旧的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 ”filter) 运行时,文件从工作树移动到索引 ,即在git add而不是在git commit时间。
(请注意, git commit -a--only--only可以在当时将文件添加到索引中)。

有关更多信息,请参阅“ autocrlf和eol之间的区别 ”。

这是我迄今为止的理解,以防万一。

core.autocrlf=truecore.safecrlf = true

你有一个存储库,所有的行结束是相同的 ,但你在不同的平台上工作。 Git将确保你的行结束符被转换为你的平台的默认值。 为什么这很重要? 假设你创build一个新文件。 您平台上的文本编辑器将使用其默认行结束符。 当您检入时,如果您没有将core.autocrlf设置为true,那么您已经为平台上默认为不同行结束的人员引入了行结尾不一致。 我也总是设定安全的,因为我想知道这个操作是可逆的。 有了这两个设置, git正在修改你的文件,但它确认修改是可逆的

core.autocrlf=false

你有一个仓库已经有混合行结束签入和修复不正确的行尾可能会打破其他的事情。 在这种情况下,最好不要告诉git转换行结束符,因为这样会加剧它devise要解决的问题 – 使差异更容易阅读和合并不那么痛苦。 有了这个设置, git不会修改你的文件

core.autocrlf=input

我不使用这个,因为这样做的原因是为了覆盖一个用例,在这个用例中你创build了一个在默认LF行结束的平台上具有CRLF行尾的文件。 我宁愿让我的文本编辑器总是保存与平台的行结束默认值的新文件。

core.autocrlf值不取决于操作系统types,但在Windows上默认值为true并且对于Linux input 。 我为提交和结帐案例探索了3个可能的值,这是得到的表格:

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

在Linux和Windows上做了一些testing。 我使用一个包含以LF结尾的行的testing文件,以及以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