248

I've read a lot of different questions and answers on Stack Overflow as well as git documentation on how the core.autocrlf setting works.

This is my understanding from what I've read:

Unix and Mac OSX (pre-OSX uses CR) clients use LF line endings.
Windows clients use CRLF line endings.

When core.autocrlf is set to true on the client, the git repository always stores files in LF line ending format and line endings in files on the client are converted back and forth on check out / commit for clients (i.e. Windows) that use non-LF line endings, no matter what format the line endings files are on the client (this disagrees with Tim Clem's definition - see update below).

Here is a matrix that tries to document the same for the 'input' and 'false' settings of core.autocrlf with question marks where I'm not sure of line ending conversion behavior.

My questions are:

  1. What should the question marks be?
  2. Is this matrix correct for the "non-question marks"?

I'll update the question marks from the answers as consensus appears to be formed.

                       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

I'm not really looking for opinions on the pros and cons of the various settings. I'm just looking for data which makes it clear how to expect git to operate with each of the three settings.

--

Update 04/17/2012: After reading the article by Tim Clem linked by JJD in the comments, I have modified some of the values in the "unknown" values in the table above, as well as changing "checkout existing | true to convert to CRLF instead of convert to client". Here are the definitions he gives, which are more clear than anything I've seen elsewhere:

core.autocrlf = false

This is the default, but most people are encouraged to change this immediately. The result of using false is that Git doesn’t ever mess with line endings on your file. You can check in files with LF or CRLF or CR or some random mix of those three and Git does not care. This can make diffs harder to read and merges more difficult. Most people working in a Unix/Linux world use this value because they don’t have CRLF problems and they don’t need Git to be doing extra work whenever files are written to the object database or written out into the working directory.

core.autocrlf = true

This means that Git will process all text files and make sure that CRLF is replaced with LF when writing that file to the object database and turn all LF back into CRLF when writing out into the working directory. This is the recommended setting on Windows because it ensures that your repository can be used on other platforms while retaining CRLF in your working directory.

core.autocrlf = input

This means that Git will process all text files and make sure that CRLF is replaced with LF when writing that file to the object database. It will not, however, do the reverse. When you read files back out of the object database and write them into the working directory they will still have LFs to denote the end of line. This setting is generally used on Unix/Linux/OS X to prevent CRLFs from getting written into the repository. The idea being that if you pasted code from a web browser and accidentally got CRLFs into one of your files, Git would make sure they were replaced with LFs when you wrote to the object database.

Tim's article is excellent, the only thing I can think of that is missing is that he assumes the repository is in LF format, which is not necessarily true, especially for Windows only projects.

Comparing Tim's article to the highest voted answer to date by jmlane shows perfect agreement on the true and input settings and disagreement on the false setting.

4

8 回答 8

144

在gitattributes手册页的属性部分core.autocrlf中可以找到有关其工作原理的最佳解释。text

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

  • core.autocrlf = true
  1. 从存储库中签出的只有字符的文本文件在您的工作树中LF被规范化;不会触及存储库CRLF中包含的文件CRLF
  2. 存储库中只有字符的文本文件在提交回存储库时从到LF标准化。包含在存储库中的文件将被原封不动地提交。CRLFLFCRLF
  • core.autocrlf = input
  1. 从存储库中签出的文本文件会将原始 EOL 字符保留在您的工作树中。
  2. 工作树中带有字符的文本文件在提交回存储库时CRLF被规范化。LF
  • core.autocrlf = false
  1. core.eol规定工作树的文本文件中的 EOL 字符。
  2. core.eol = native默认情况下,这意味着工作树 EOL 将取决于 git 的运行位置:CRLF在 Windows 机器上,或LF在 *nix 中。
  3. 存储库gitattributes设置确定提交到存储库的 EOL 字符规范化(默认为LF字符规范化)。

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

于 2010-12-13T02:45:27.843 回答
72

混合平台项目中的 EOL 问题让我的生活痛苦了很长时间。当存储库中已经存在具有不同和混合 EOL 的文件时,通常会出现问题。这意味着:

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

这是如何发生的不是这里的问题,但它确实发生了。

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

                 | 产生的转换时 | 结果转换时
                 | 提交各种文件 | 从回购中签出-
                 | EOLs INTO 回购和 | 里面有混合文件和
                 | core.autocrlf 值:| core.autocrlf 值:           
-------------------------------------------------- ------------------------------
文件 | 真实 | 输入 | 假 | 真实 | 输入 | 错误的
-------------------------------------------------- ------------------------------
Windows-CRLF | CRLF -> LF | CRLF -> LF | 原样 | 原样 | 原样 | 原样
Unix-LF | 原样 | 原样 | 原样 | LF -> CRLF | 原样 | 原样
Mac-CR | 原样 | 原样 | 原样 | 原样 | 原样 | 原样
混合-CRLF+LF | 原样 | 原样 | 原样 | 原样 | 原样 | 原样
混合-CRLF+LF+CR | 原样 | 原样 | 原样 | 原样 | 原样 | 原样

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

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

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

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

另请注意,“旧”Mac EOLCR也永远不会被转换。
这意味着,如果一个写得不好的 EOL 转换脚本试图通过仅将s 转换为 s 来转换带有CRLFs+ s 的混合结尾文件,那么它将使文件处于与“孤独” s 的混合模式,无论 a被转换为. 然后,即使在模式下,Git 也不会转换任何内容,并且 EOL 的破坏仍在继续。这实际上发生在我身上,并且把我的文件弄得一团糟,因为一些编辑器和编译器(例如 VS2010)不喜欢 Mac EOL。LFLFCRLFCRCRLFCRCRLF
true

我想真正处理这些问题的唯一方法是偶尔input通过检查或模式下的所有文件来规范整个 repo false,运行适当的规范化并重新提交更改的文件(如果有的话)。在 Windows 上,可能会继续使用core.autocrlf true.

于 2012-12-26T11:23:42.983 回答
50

core.autocrlf值不依赖于操作系统类型,但在 Windows 上,默认值为trueLinux - 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 ║
╚═══════════════╩══════════════╩══════════════╩══════════════╝
于 2016-12-22T11:41:34.533 回答
40

随着即将到来的 Git 1.7.2,“eol 转换”方面的事情即将发生变化:

core.eol正在添加/发展新的配置设置:

这是当前(我的系列中的最后一个)中的“添加core.eol”配置变量“提交的替代品。 它并没有暗示“ ”是“”的替代品,而是明确指出,该事实仅适用于希望在没有文本文件规范化的存储库上的工作目录中使用 CRLF 的用户。 启用后,“core.eol”将被忽略。pu
core.autocrlf=true* text=autoautocrlf

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

[core]
  autocrlf = true

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

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提交92cce13、4b 422提交 bb211b4提交 92cce13提交 320d39c(2016 年 2 月 5 日),作者Torsten Bögershausen ( tboegi)
(由Junio C Hamano 合并 -- gitster--提交 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在评论中添加的那样:

当文件从 work-tree 移动到 index 时,所有这些转换(任何 EOL 转换eol=autocrlf设置,以及“ clean”过滤器)都会运行,即在此期间而不是在某个时间。 (但请注意,当时or确实将文件添加到索引中。)git addgit commit
git commit -a--only--include

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

于 2010-07-09T04:21:44.443 回答
7

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

core.autocrlf=truecore.safecrlf = true

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

core.autocrlf=false

您有一个签入混合行结尾的存储库,修复不正确的行结尾可能会破坏其他内容。在这种情况下,最好不要告诉 git 转换行尾,因为那样会加剧它旨在解决的问题 - 使差异更易于阅读和合并不那么痛苦。使用此设置,git 不会修改您的文件

core.autocrlf=input

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

于 2014-01-20T20:27:34.677 回答
4

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

对于Checkin (git add, git commit)

  1. 如果text属性为Set, Set value to 'auto',则转换发生在文件已使用“CRLF”提交的情况下
  2. 如果text属性是Unset:什么都没有发生,enen forCheckout
  3. 如果text属性是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.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. 没有,什么也没有发生,core.eol 在text属性为时无效Unspecified

默认行为

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

  1. 签入,没有任何反应
  2. 结帐,没有任何反应

结论

  1. 如果text设置了属性,则签入行为取决于自身,而不是 autocrlf
  2. autocrlf 或 core.eol 用于结帐行为,而 autocrlf > core.eol
于 2018-03-08T02:55:52.203 回答
3

在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  
于 2017-02-23T08:51:45.910 回答
0

core.autocrlf=true导致提交的声明CRLF -> LF都是错误的!正如您将看到的那样,这并不是那么简单...

文档说该设置对应于...“<code>text=auto in .gitattributesand core.eolbeing set to crlfin git config”...究竟是什么意思?

这意味着,如果一个文件没有设置.gitattributes text属性,并且 if core.autocrlfis true,它现在取决于您提交的文件是否是新的(在这种情况下,是的,它将在 git repo 数据库中标准化为 LF ),或者它是否是您编辑并且现在正在提交的现有文件(在这种情况下不会发生任何事情......除非您git add --renormalize .在这种情况下运行它将在 git repo 数据库中标准化)。

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

因此,您真正应该关注的是.gitattributes在所有文件上使用默认设置,即:

* -text
# followed by specialization

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

*  text=auto
# followed by specialization

这意味着 git 自动检测为非二进制(文本)并且LF在 git 数据库中具有的所有文件(专业化除外) [见注 1.],将在CRLF以下任何时候获取:
    • core.autocrlfis true,或
    • core.eolis crlf,或
    • core.eolis native(默认)并且您在 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(即没有其他专业化),因为我假设您的存储库.gitattribute在创建时已正确规范化

于 2021-03-28T20:45:02.267 回答