我该如何强制Git在Windows下使用LF而不是CR + LF?

601
我想强制Git仅使用LF而不是CR + LF来检出Windows下的文件。 我检查了两个配置选项,但无法找到正确的设置组合。
我想将所有文件转换为具有LF换行符,并保留文件中的LF
备注:我使用了autocrlf = input,但这只会在提交文件时修复它们。 我想强制它使用LF获取它们。
可能我没有表达清楚: 该存储库已经使用LF,但使用Git for Windows检出的文件使用CR + LF, 我想强制Git使用LF获取它们: 强制Unix换行符。
$ git config --list | grep crlf
core.autocrlf=input

3
autocrlf=input是正确的选项。当然,它不能保护你免受仓库中真正存在cr+lf文件或者在使用其他工具创建cr+lf文件后添加到git时的影响。如果这个选项无法解决你的问题,那么你遇到了什么问题? - CB Bailey
5
存储库中的文件已经使用了只有 LF 的换行符,但是当我在 Windows 下获取它们时,msysgit 会将它们转换为 CR+LF - sorin
你的配置可能出了些问题;我刚在我的msysgit安装上测试了一下。当autocrlf设置为input时,git会将lf行尾保持不变。你可以发一下git config的输出吗? - CB Bailey
1
在这种情况下,我建议您记录一个错误;最好指向一个展示您问题的测试存储库,并包括重现步骤,因为您看到的行为绝对是错误的(但我无法重现它)。 - CB Bailey
3
一个小贴士是确保你在运行git命令时使用的是你想要的'git'。例如,你可能在Windows上安装了git,在Cygwin上也安装了git,所以请确保你已经设置了正确的git配置。 - lfred
显示剩余5条评论
6个回答

728
将 Windows 中的 LF 结尾转换为正确方式是首先将 core.autocrlf 设置为 false
git config --global core.autocrlf false

如果你使用msysgit,需要进行以下操作,因为它会在系统设置中将其设置为true

现在,git不会进行任何行尾标准化。如果您想对检查的文件进行标准化,请执行以下操作:在所有文件的.gitattributes中设置text=auto

* text=auto

core.eol 设置为 lf

git config --global core.eol lf

现在你也可以通过运行以下命令将单个代码库切换为CRLF(在工作目录中!)

git config core.eol crlf

配置完成后,您可能想让git规范化repo中的所有文件。要做到这一点,请转到repo的根目录并运行以下命令:

git rm --cached -rf .
git diff --cached --name-only -z | xargs -n 50 -0 git add -f

如果您现在希望Git也规范化您的工作目录中的文件,请运行以下命令:

git ls-files -z | xargs -0 rm
git checkout .

4
在执行 git diff --cached --name-only -z | xargs -0 git add 命令后,我遇到了致命的路径规范错误:“”未匹配任何文件。 - CMCDragonkai
3
git diff --cached --name-only 的输出结果是什么? - Chronial
36
或许值得一提的是,在克隆相关代码库时,你可以设置这个配置,比如 git clone --config core.autocrlf=false <repo 路径>。请注意,务必在克隆代码库的同时进行此项设置。 - Chris Long
2
下面的命令是做什么的: 首先从git中删除所有文件(但实际上保留它们!) git rm --cached -rf . 然后只显示更改的文件名(您删除的文件)-z:空终止|添加它们(-0:空终止) git diff --cached --name-only -z | xargs -0 git add -f <- 这确保了您的git历史记录很好地使用LF。空终止允许在文件名中出现奇怪的字符。 - Fee
1
然后,您从工作目录中删除所有文件(xargs在ls-files的所有输出上执行“rm”命令): git ls-files -z | xargs -0 rm 并检出工作树(因此将实际文件恢复到您的暂存更改)。 它有效!另外不要单独运行块中的命令,否则可能会丢失未提交的更改 :) - Fee
显示剩余7条评论

433
我经常回到这个问题,尽管它的其他答案对我来说都不完全正确。
话虽如此,对我来说正确的答案是其他答案的混合体。
我发现以下方法有效:
git config --global core.eol lf
git config --global core.autocrlf input

对于在全局设置之后检出的存储库(Git存储库),一切都将作为存储库中的内容被检出 - 希望是 LF\n)。
任何CRLF都将在检入时转换为LF

如果您已经检出了一个现有存储库,该存储库具有正确的行结尾符但工作副本没有,则可以运行以下命令进行修复:

git rm -rf --cached .
git reset --hard HEAD

这将递归地(-r)删除(rm)当前目录(.)中除了你编辑过的文件(--cached)以外的所有文件,没有提示(-f)。然后,reset会将所有这些文件恢复到其真实行结尾状态(与存储库中的匹配)。

如果您需要修复存储库中文件的行结尾,我建议使用像IntelliJ或Sublime Text这样的编辑器批量操作,但我相信任何好的编辑器都可能支持此功能。


2
我们有一个单一的仓库,其中包含需要不同行尾处理的子目录。因此,设置全局选项对此无效。即使在单个仓库中也是如此。您如何在.gitattributes中应用这些相同的设置? - RobG
4
core.autocrlf input 选项会覆盖 core.eol 设置,因此同时设置这两个选项是多余的。(参见 https://www.git-scm.com/docs/git-config) - Andrew Marshall
1
谢谢你的帮助,我已经征服了Lint和Linux,并且现在可以提交文件了。 - GC_
我认为作者设置了 core.eol 是因为在某些情况下,一些编辑器或其他应用程序可能会覆盖 core.autocrlf 的值,因此这个设置被用作备份。 - ttimasdf
1
在进行任何 gitfu 操作之前,一定要提交所有的工作。这个答案也已经有将近十年的历史了,我不知道它是否仍然适用。 - Ben Liyanage
显示剩余3条评论

187

OP在他的问题中补充道:

使用msysgit检出的文件使用CR+LF,我想强制msysgit以LF获取它们

第一步是创建一个简单的.gitattributes文件:

# 2010
*.txt -crlf

# 2020
*.txt text eol=lf 

grandchild在评论中所述,参考.gitattributes End-of-line conversion,为了避免对正确的eol文件进行任何CRLF转换。

我一直建议使用 git config --global core.autocrlf false来禁用任何转换(这将适用于所有版本控制的文件)

请参阅跨平台git配置的最佳实践?

自Git 2.16起(2018年第1季度),您可以使用git add --renormalize .立即应用这些.gitattributes设置。


但更为强大的第二步涉及使用 gitattribute过滤驱动程序 并添加一个smudge步骤。

filter driver

每当您更新工作树时,一个脚本可以针对您在.gitattributes中指定的文件,强制使用LF eol和任何其他您想要强制执行的格式选项。
如果"clear"脚本没有做任何事情,在提交后,您将转换文件,应用完全符合您需要的格式。

1
一个问题:*.txt 是指所有扩展名为 .txt 的文件还是所有文本文件(非二进制文件)?我无法列出项目中所有文件扩展名的清单。 - sorin
2
@Sorin:所有扩展名为.txt的文件。最好先在特定组上建立并测试它,然后再推广到*,并添加一个否定规则!*.xyz...来排除一些文件。 - VonC
2
现在.gitattributes的行应该是这样的:*.txt text eol=lf,参见https://www.git-scm.com/docs/gitattributes。 - grandchild
@grandchild 谢谢。我已经将您的评论包含在答案中以增加可见性。 - VonC
1
我猜在我们添加了.gitattributes文件之后,我们需要执行git add --renormalize .命令。 - KRoy
@shuva 是的,但只有在 Git 2.16 及以上版本才支持:https://dev59.com/fGw05IYBdhLWcg3wkivX#47580886 - VonC

136

背景

如果您想要强制所有用户在文本文件中使用LF行结束符,但无法确保所有用户更改其git配置文件,那么从git 2.10开始就可以实现。需要2.10或更高版本,因为2.10修复了text = auto与eol = lf一起使用的行为来源

解决方案

在您的git存储库的根目录中放置.gitattributes文件,并包含以下内容:

* text=auto eol=lf

提交它。

可选微调

您还可以在存储库的根目录中添加.editorconfig,以确保现代工具在创建带有所需行结尾的新文件时使用该配置。

# EditorConfig is awesome: http://EditorConfig.org

# top-most EditorConfig file
root = true

# Unix-style newlines with a newline ending every file
[*]
end_of_line = lf
insert_final_newline = true

10
这对我来说是最好的解决方案。我还结合了http://editorconfig.org,这样在Intellij中编写时我会写出LF EOLs。 - Jazzepi
2
这绝对是最好的解决方案。无需手动运行任何配置命令! - Cameron Tacklind
这个单行的 .gitattributes 条目是最好的,其他解决方案可能会令人困惑。 - Zoltán Hajdú
如果我想要能够保留行尾与代码库完全一样的结束符,不论它们是什么,该怎么办?我使用 Windows 操作系统,但我使用各种不同的代码库,每个库可能都有自己的规范。我只想告诉 GitHub:「请不要改变行尾结束符。当我进行检出时,将它们保持和代码库完全一样,当我进行提交时,也请保持和我的代码完全一样。」然后我可以告诉我的编辑器不要更改行尾结束符,这样每个人都会很满意。 - davejbur
根据我的理解,设置“git config --global core.autocrlf false”会让Windows感到困惑;而设置“git config --global core.autocrlf true”意味着文件将始终以CRLF检出并以LF检入,并且在我的设置中,在“.gitattributes”中设置“* text=auto”似乎没有任何影响。 - davejbur
显示剩余2条评论

34

core.autocrlf=input 是你想要的正确设置,但你可能需要执行git update-index --refresh和/或git reset --hard命令才能使更改生效。

core.autocrlf 设置为 input 时,git 不会在检出时应用换行符转换(因此,如果仓库中有LF,则会得到LF),但它将确保在你搞砸并在工作副本中引入一些CRLF的情况下,它们不会进入到仓库中。


21
命令应为: git rm --cached -r . && git reset --hard - koppor

0

您可以在以下链接中找到解决此问题的方法: https://help.github.com/en/github/using-git/configuring-git-to-handle-line-endings

以下是在 Windows 上解决此问题的简化描述:

全局设置换行符 使用 git config core.autocrlf 命令可更改 Git 处理换行符的方式。它只接受一个参数。

在 Windows 上,您只需将 true 传递给配置即可。例如: C:>git config --global core.autocrlf true

祝您好运,希望我能帮到您。


我发现在Windows上,我可以随时运行git add --renormalize .命令,并且它会接受所有当前文件的行尾。 - Spencer Williams

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