Git使用CRLF替换LF

1219
在Windows机器上,我使用git add添加了一些文件。我收到了警告信息:

LF将被替换为CRLF

这种转换会有什么影响?

20
@apphacker,标准化行尾比在比较两个文件时自己更改它们要少让人烦恼。(当然,如果您不同意,那么可以保持关闭core.autocrlf功能)。 - RJFalconer
3
除非整行被触碰,否则为什么行末会不同。 - Bjorn
4
我经常会涉及到很多行代码,因为我正在尝试不同的想法,并添加跟踪语句以查看它们的工作情况等。然后,我可能只想提交对两三行代码的更改,而让 git 完全忽略其他代码,因为我认为它们已经被恢复成了原来的样子。 - Tyler
7
@MatrixFrog: 你的编辑器好像出了问题,无法自动检测行尾结束符是哪种。它是哪一种呢? 我工作于混合项目中,该项目必须在同一个存储库中同时包含一些 LF 文件和一些其他的 CRLF 文件。对于任何现代编辑器来说都不是问题。让版本控制(或文件传输)搞乱行尾结束符来解决编辑器限制是最糟糕的想法——仅从下面的解释长度就可以明显看出。 - MarcH
7
我知道的唯一一个在现代编辑器中做错事情的是Visual Studio。Visual Studio可以轻松地打开带有LF行尾的文件。如果您插入新行,它将插入CRLF,并保存混合行尾。微软拒绝修复此问题,这是一个相当大的瑕疵,否则这个IDE还是相当不错的:--( - Jon Watte
显示剩余7条评论
25个回答

1524

这些错误消息是由于Windows上core.autocrlf的默认值不正确所导致。

autocrlf的概念是透明地处理行尾转换。它做到了!

坏消息:需要手动配置该值。

好消息:每个Git安装(也可以每个项目设置)只需要配置一次。

autocrlf如何工作

core.autocrlf=true:      core.autocrlf=input:     core.autocrlf=false:

     repository               repository               repository
      ^      V                 ^      V                 ^      V
     /        \               /        \               /        \
crlf->lf    lf->crlf     crlf->lf       \             /          \
   /            \           /            \           /            \

在这里,crlf代表Windows风格的行尾标记,lf代表Unix风格的行尾标记(自Mac OS X以来也在Mac上使用)。

(对于上述三个选项中的任何一个,都不会影响pre-osx中的cr。)

在Windows下什么时候会出现此警告?

    - 如果您的文件中有Unix风格的lf(=很少出现),则 autocrlf=true
    - 如果您的文件中有Windows风格的crlf(=几乎总是),则 autocrlf=input
    - 如果 autocrlf=false,则永远不会出现此警告!

这个警告是什么意思?

警告“LF will be replaced by CRLF”表示:在提交-检出周期中,您的unix风格的LF(由于autocrlf=true)将被替换为Windows风格的CRLF,Git不期望您在Windows下使用Unix风格的LF。

警告“CRLF will be replaced by LF”表示:在提交-检出周期中,您的Windows风格的CRLF(由于autocrlf=input)将被替换为Unix风格的LF,请勿在Windows下使用input

另一种展示autocrlf工作方式的方法

1) true:             x -> LF -> CRLF
2) input:            x -> LF -> LF
3) false:            x -> x -> x

其中x可以是CRLF(Windows风格)或LF(Unix风格),箭头表示

file to commit -> repository -> checked out file

如何修复

core.autocrlf 的默认值在 Git 安装过程中选择,并存储在系统范围的 gitconfig 文件中(Windows 上为 %ProgramFiles(x86)%\git\etc\gitconfig,Linux 上为 /etc/gitconfig)。此外,还存在以下级联配置:

   – 位于 ~/.gitconfig 的“全局”(每个用户)gitconfig,
   – 位于 $XDG_CONFIG_HOME/git/config$HOME/.config/git/config 的另一个“全局”(每个用户) gitconfig,以及
   – 工作目录中的 .git/config 的“本地”(每个仓库) gitconfig。

因此,在工作目录下键入 git config core.autocrlf 以检查当前使用的值并执行以下操作:

   – git config --system core.autocrlf false            # 系统范围的解决方案
   – git config --global core.autocrlf false            # 每个用户的解决方案
   – git config --local core.autocrlf false              # 每个项目的解决方案

警告

    – git config 设置可以被 gitattributes 设置覆盖。
    – 只有在添加新文件时才会发生 crlf -> lf 转换,仓库中已存在的 crlf 文件不受影响。

建议(对于 Windows):

    - 如果您计划在 Unix 下使用该项目(并且不想配置编辑器/IDE 使用 Unix 换行符),请使用 core.autocrlf = true
    - 如果您只计划在 Windows 下使用该项目(或者已经配置了编辑器/IDE 使用 Unix 换行符),请使用 core.autocrlf = false
    - 除非你有充分的理由(例如,在 Windows 下使用 Unix 工具或遇到 makefile 问题),否则绝不使用 core.autocrlf = input

PS:安装 Git for Windows 时应该选择什么?

如果您不打算在 Unix 下使用任何项目,请勿同意默认的第一个选项。选择第三个选项(检出为原样,提交为原样)。您将永远不会看到此消息。

PPS:我的个人偏好是将编辑器/IDE配置为使用 Unix 样式的换行符,并将 core.autocrlf 设置为 false

更新(2022)

自2018年以来,git可以使用 --renormalize 命令修复现有代码库中的行尾问题。


23
很混乱。我在编辑器中设置了LF,整个代码库都使用LF,全局autocrlf设置为false,且我的主目录中的核心gitconfig也设置为false。但仍然收到消息提示LF被替换为CRLF。 - isimmons
38
如果您已经配置了编辑器使用Unix风格的换行符,请将core.autocrlf设置为输入模式吧。从您的回答中我理解到,将其设置为输入模式可以确保仓库和工作目录始终具有Unix风格的换行符。那么,为什么在Windows系统中您绝对不想要这样做呢? - Hubro
4
不过有些奇怪。我在全局和本地配置中都将 core.autocrlf 设置为false,但在尝试提交时仍然收到警告。git版本是2.7.0。 - digory doo
8
明白了:.gitattributes 可以覆盖配置设置。 - digory doo
12
@AntonyHatchkins的意思是,使用input的好处在于,如果我无意中在某个地方使用了CRLF(比如你可能会在记事本中进行快速编辑而不是在配置良好的IDE中进行编辑),它就可以将我的行结束符转换为LF,同时不影响所有有意的LF。 使用false的缺点是,如果我不小心使用了CRLF,可能会将其提交到仓库中。 input可以防止这种情况发生! 所以input> false,对吗? - Henrik Heimbuerger
显示剩余39条评论

837

Git有三种处理行尾的模式:

# This command will print "true" or "false" or "input"
git config core.autocrlf

您可以通过在上述命令行中添加一个附加参数truefalse来设置要使用的模式。

如果core.autocrlf设置为true,则表示每次将文件添加到Git存储库时,Git都会将所有CRLF行尾转换为仅LF,然后再将其存储在提交中。每当您git checkout某些内容时,所有文本文件都会自动将其LF行尾转换为CRLF行尾。这允许跨使用不同行尾样式的平台开发项目,而不会因为每个编辑器始终一致地更改行尾样式而导致提交非常嘈杂。

这种方便的转换的副作用是,这就是您看到的警告的原因,如果您最初编写的文本文件具有LF行尾而不是CRLF,则通常会像往常一样以LF格式存储,但稍后检出时它将具有CRLF行尾。对于普通文本文件,这通常没问题。在这种情况下,警告只是“供您参考”,但是如果Git错误地将二进制文件评估为文本文件,则这是一个重要的警告,因为Git随后会破坏您的二进制文件。

如果core.autocrlf设置为false,则永远不会执行换行符转换,因此将按原样检入文本文件。通常情况下,只要您的所有开发人员都在Linux上或全部在Windows上,这种方法就可以正常工作。但是根据我的经验,我仍然会得到具有混合行尾的文本文件,这最终会导致问题。

作为Windows开发人员,我的个人偏好是将设置保留为开启状态。

请参考git-config获取更新的信息,其中包括"input"值。


130
如此说道(https://dev59.com/lHM_5IYBdhLWcg3wvF3J#1250133), 我不同意这种设置并将其关闭(使用Notepad++或其他可以处理--并且保留发现的任何行尾字符的编辑器)。 - VonC
24
我喜欢这个答案,而且更愿意将 autocrlf 设置为 true。作为替代方案,有没有一种自动消除警告信息的方法? - Krisc
13
将这篇写得很好的答案与core.eol设置进行比较,并结合.gitattributes配置可能会更好。我一直在通过实验来弄清楚它们之间的差异和重叠,但是这非常令人困惑。 - seh
5
为了获得更长久的解决方案,请将您的.gitconfig更改为以下内容:[core] autocrlf = false。 - RBZ
11
有没有简单的方法可以消除警告?我想将它设置为"true"并确认已经设置为"true",我不想一直看到所有的警告...没事的... :p - UmaN
显示剩余13条评论

347

如果您已经查看了代码,则文件已经被索引。更改Git设置后,例如通过运行以下命令:

git update-index --no-assume-unchanged <file>

git config --global core.autocrlf input

您应该使用以下方法刷新索引:

git rm --cached -r .

使用以下命令重写 Git 索引:

git reset --hard

注意:这将删除您的本地更改。在执行此操作之前,请考虑将它们存储起来。


来源:配置 Git 处理行尾


54
感谢您提供了一个简单、跨平台、明确的方法来修复它,而不是对配置含义进行大量讨论。 - Eris
3
如果运行 "git reset --hard" 命令,是否会导致我本地的修改丢失?我只是按照之前提到的所有评论操作。 - Freddy Sidauruk
7
是的,您本地的更改将会丢失。--hard参数将重置索引和工作树,因此任何对已跟踪文件的更改都将被丢弃。https://git-scm.com/docs/git-reset - Jacques
5
如果你修改了core.autocrlf设置并且想要在运行git reset --hard命令后不重新转换行尾符号,那么你需要使用命令git rm --cached -r .来清理Git索引。这个命令可以使得修改的设置生效。 - wisbucky
3
您提供的链接(关于在更改 core.autocrlf 配置后刷新存储库)并没有使用您建议的命令,而是使用了 git add --renormalize .。因此,自2015年以来,推荐的操作程序可能已更改。@user2630328也许可以详细说明一下区别。 - Daniel K.
显示剩余8条评论

95
git config core.autocrlf false

7
请确保在代码库根目录内运行此命令。 - TheTechGuy
53
我不明白这有什么用处。一半的人需要将 autocrlf 设为 true 才能正常工作,而另一半则需要将其设为 false/input。那么,他们是应该随机地将这些零散的答案扔到控制台上,直到找到可行的方案吗?这并不是有效的方法。 - Zoran Pavlovic
1
我遇到了一个错误:“致命错误:不在git目录中”。我尝试使用cd进入C:\Program Files\Git和C:\Program Files\Git\bin目录。 - pixelwiz
2
@mbb将autocrlf设置为false只是把问题推给了你项目的每个用户。 - jpaugh
6
这条命令仅为该项目设置属性(因此您需要在 git 存储库下运行它)。如果您想全局设置,可以使用 git config --global core.autocrlf false 命令代替。 - Michaël Polla

55

在Windows上,可以使用Git Bash来获取unix2dosdos2unix。您可以使用以下命令执行UNIX(LF)→ DOS(CRLF)转换。因此,您将不会收到警告。

unix2dos filename

或者

dos2unix -D filename

但是,不要在任何已存在CRLF文件上运行此命令,否则每隔一行将会出现空的新行。 dos2unix -D 文件名 在每个操作系统上都无法使用。请检查此链接以获取兼容性信息。
如果由于某种原因需要强制执行该命令,则使用--force。如果显示无效,则使用-f

1
这是帮助选项的内容:--u2d,-D 执行UNIX -> DOS转换 - Larry Battle
1
@Rifat 我有点困惑。你的评论说 dos2unix -D 会将 Windows 的换行符转换为 Linux 的换行符。 这不就是 DOS(CRLF) -> UNIX(LF) 转换吗? 然而,dos2unix -h 显示 -D 将执行 UNIX(LF) -> DOS(CRLF) 转换。 dos2unix 更多信息:http://gopherproxy.meulie.net/sdf.org/0/users/pmyshkin/dos2unix - Larry Battle
1
@LarryBattle 是的,你关于-D的说法是正确的。实际上,我在回答时还是Windows用户。而且,一年多后我成为了Mac用户并发表了这条评论:D 顺便说一句,谢谢你的澄清。 - Rifat
1
这对我有用。我正在使用Cygwin,它似乎不支持-D开关,但是有一个“unix2dos”命令,可以完成同样的工作。虽然我希望知道是什么原因导致了问题-我已经将core.autocrlf设置为false,并且这是一个仅限Windows的存储库。 - Richard Beier
我正在使用Windows Bash,但似乎不支持dos2unix 6.0.4(2013-12-30)中的-D--u2d开关。 - Andrei Krasutski
显示剩余4条评论

43

谈到这个主题时,通常会提到一篇关于行尾的GitHub文章

在我的个人经验中,使用经常推荐的 core.autocrlf 配置设置效果很不稳定。

我正在使用带有Cygwin的Windows,在不同时间处理Windows和Unix项目。即使是我的Windows项目有时也会使用需要Unix(LF)行结尾的Bash shell脚本。

对于像我这样的混合环境,将全局 core.autocrlf 设置为任何选项都无法良好运作。尽管该选项可以在本地(存储库)Git配置上设置,但即使在包含Windows和Unix相关内容的项目中(例如,我有一个带有一些Bash实用程序脚本的Windows项目),那也不够好。

我发现最好的选择是创建每个存储库的.gitattributes文件。这篇GitHub文章提到了它。

来自该文章的示例:

# Set the default behavior, in case people don't have core.autocrlf set.
* text=auto

# Explicitly declare text files you want to always be normalized and converted
# to native line endings on checkout.
*.c text
*.h text

# Declare files that will always have CRLF line endings on checkout.
*.sln text eol=crlf

# Denote all files that are truly binary and should not be modified.
*.png binary
*.jpg binary
在我的一个项目存储库中:
* text=auto

*.txt         text eol=lf
*.xml         text eol=lf
*.json        text eol=lf
*.properties  text eol=lf
*.conf        text eol=lf

*.awk  text eol=lf
*.sed  text eol=lf
*.sh   text eol=lf

*.png  binary
*.jpg  binary

*.p12  binary

设置需要做更多的事情,但每个项目只需一次,并且在使用该项目时任何操作系统上的贡献者都不会遇到换行符的问题。


目前遇到这个问题,尝试使用Cygwin脚本来管理存储库,其中包括其他基本文本文件。您如何处理没有扩展名的文件(例如“fstab”,“sshd_config”)?链接的文章没有涵盖该场景。 - Mike Loux
1
@MikeLoux 试试这个方法:https://dev59.com/rKLia4cB1Zd3GeqPrvsI#44806034 - Gene Pavlovsky
我发现 text=false eol=false 的作用与 binary 类似。这个听起来对吗?指明“我知道这些是文本文件,但我不想将它们标准化”可能会很有用。 - joeytwiddle

35

我认为Basiloungas的回答是接近答案的,但已经过时了(至少在Mac上)。

打开~/.gitconfig文件并将safecrlf设置为false:

[core]
       autocrlf = input
       safecrlf = false

那样似乎会忽略换行符(不过对我来说起作用了)。


1
应该是safecrlf(带有“f”)。 - alpipego

21
在Vim中,打开文件(例如::e YOURFILEENTER),然后
:set noendofline binary
:wq

4
仅使用 vim 进行编辑将保留所有行结尾。 - esengineer
我一直在处理一些Cocoapods文件的问题。上述方法解决了其中大部分问题;对于剩下的,s/{control-v}{control-m}//就可以解决了。这两个控制码组合在一起会产生^M,这是我们在OS X上经常看到的Windows文件中的符号。 - janineanne

19

我之前也遇到过这个问题。

SVN 不进行任何行尾转换,因此提交的文件将保留 CRLF 行尾。如果你使用 git-svn 将项目放入 git 中,则CRLF 行尾会继续保留在 git 存储库中,而这不是 git 预期发现自己处于的状态——默认情况下仅检查 unix/linux(LF) 行尾。

然后,在 windows 上检出文件时,autocrlf 转换会保持文件原样(因为它们已经具有当前平台的正确行尾),但是决定是否与检入文件存在差异的过程在比较之前执行反向转换,结果是将检出文件中的 LF 与存储库中意外的 CRLF 进行比较。

据我所见,你的选择是:

  1. 重新导入代码到新的 git 存储库中,而不使用 git-svn,这将意味着行尾在初始 git commit --all 中被转换。
  2. 将 autocrlf 设置为 false,并忽略行尾不符合 git 首选风格的事实。
  3. 关闭 autocrlf 检出文件,修正所有行尾,重新检入所有内容,然后再次打开。
  4. 重写存储库的历史记录,使原始提交不再包含 git 无法预期的 CRLF。 (有关历史重写的常规警告适用)

脚注: 如果你选择选项#2,则我的经验是一些辅助工具(rebase、patch 等)无法处理 CRLF 文件,你最终将拥有混合 CRLF 和 LF(不一致的行尾)的文件。我不知道有什么方法可以同时达到两者的最佳效果。


2
我认为有第四个选项可以添加到您的列表中,假设您有能力重写历史记录:您可以采用最初使用git-svn创建的git存储库,并重写其历史记录,以不再具有CRLF换行符。这将使您的规范化换行符向后延伸整个svn历史记录。用户keo在https://dev59.com/jnNA5IYBdhLWcg3wUMDn#1060828上提供了一个解决方案。 - Chris
关于你的脚注:“rebase”对CRLF没有问题。我所知道的唯一问题是标准的git合并工具只会使用LF插入其冲突标记("<<<<<<",">>>>>>"等),因此带有冲突标记的文件将具有混合的行结尾。但是,一旦你删除这些标记,一切都没问题了。 - sleske
可能git的处理方式在过去的三年中发生了变化,这是我当时的直接经验,自那以后我没有再需要重新访问这个特定的问题。你的情况可能会有所不同。 - Tim Abell
2
@sleske 从git 2.8开始,合并标记将不再引入混合行结尾。请参见https://dev59.com/zGMm5IYBdhLWcg3wIsbj#35474954 - VonC
@VonC:太酷了。这对我需要在Windows上工作的时候很有帮助。 - sleske

18

Windows中的大多数工具也接受文本文件中的简单LF。例如,您可以在名为“.editorconfig”的文件中控制Visual Studio的行为,并使用以下示例内容(部分):

Most of the tools in Windows also accepts a simple LF in text files. For example, you can control the behaviour for Visual Studio in a file named '.editorconfig' with following example content (part):

 indent_style = space
 indent_size = 2
 end_of_line = lf    <<====
 charset = utf-8

只有原版的Windows 记事本 无法与LF一起使用,但还有一些更合适的简单编辑器工具可用!

因此,在Windows中的文本文件中应该使用LF。这是我的信息,并且强烈推荐!没有任何理由在Windows中使用CRLF!

(同样的讨论也出现在C / C ++中包含路径中使用 \ 。那是牛粪。使用斜杠#include <pathTo / myheader.h>,它是C / C ++标准,所有Microsoft编译器都支持它)。

因此,Git的正确设置为:

git config core.autocrlf false

我的信息:忘记像 dos2unixunix2dos 这样的旧思维程序。在你的团队中要明确,LF 在 Windows 下是适用的。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接