禁用 git EOL 转换

Posted

技术标签:

【中文标题】禁用 git EOL 转换【英文标题】:Disable git EOL Conversions 【发布时间】:2014-03-16 08:52:03 【问题描述】:

我试图让 git 不为任何操作更改任何行尾。不幸的是,这似乎无关紧要。我已将其简化为以下测试用例,它有尽可能多的不同机制来禁用此行为。


从两台机器开始(Windows 计算机 = A,Linux 计算机 = B) 在两台机器上:git config --global core.autocrlf false 在两台机器上:git config --global core.eol crlf(以防万一)
在 A 上创建新存储库。从一个空文件夹: git init --shared(然后取消隐藏创建的.git目录) 在存储库中创建一个新文件.gitignore 在存储库中创建一个新文件.gitattributes,使用一行:* -text git add .,然后是 git commit -m "initial commit" 来解决,例如this。 git branch master_recv 添加遥控器 在包含 CRLF 的存储库中创建一个新文件 document.txt 提交:git add -A,然后是git commit -m "<something>" 请注意,A 的 document.txt 仍然包含 CRLF(删除它并使用 --hard 重置会返回仍然带有 CRLF 的版本)
SCP 整个目录到计算机 B 添加一个包含 CRLF 的新文件 new file 提交:git add -A,然后是git commit -m "<something>" 请注意,B 的 document.txt 和 B 的 new file 仍然包含 CRLF
将B的master拉到A:git pull <remote> master:master_recv A 的 document.txt 已更改为 LF。添加的文件new file 也包含LF。

如果 B 是 Windows 机器,则不会出现此问题。

【问题讨论】:

core.autocrlf 总是 是假的吗?听起来您的存储库中已经有 \n 行尾? no 设置可将存储库中的 \n 更改为工作目录中的 \r\n 它并不总是被设置(例如最初创建 repo 时)。但是,回购中不应该有任何 CR 行结尾。此外,我再次希望发生任何变化。 我问是因为您的设置应该将您的行尾保留为 CRLF。您能否在您的存储库中发布一些文件它的对象 ID 只是为了我(诚然可能很烦人)的启迪? @EdwardThomson 你是什么意思?回购不是公开的(因为 Linux 机器不是)。我假设你想要一个示例文件。见编辑。 是的,我同意该文件具有 CRLF 行结尾。您能否澄清一件事:您提到“windows 机器的换行符更改为 CR!”这肯定是一个错字,还是你真的得到了 Mac OS 9 风格的回车行结尾? 【参考方案1】:

一个简单的解决方案是:

确保 all 存储库的 core.autocrlf 设置为 false:git config --global core.autocrlf false Git 2.16 (Q1 2018) and above,运行git add --renormalize . 否则,请重新克隆您的存储库,并检查没有完成 EOL 转换。

如果有自动完成的转换,这意味着一个 .gitattributes core.eol directive 在 repo 中。

用Git 2.8+ (March 2016),检查是否还有eol转换用:

git ls-files --eol

【讨论】:

今天不要使用autocrlf!未设置的autocrlf 等同于false。你落后于 Git 的流行趋势 和上面一样,我试过这个(虽然没有使用全局标志),但它没有用。 git 版本是1.8.5.2 @IanMallett "此时,Linux 机器似乎仍然有 CRLF":它会直到你重新规范化它的内容,或者克隆它(就像你在 windows 上所做的那样) 如果你只想为一个 repo 做这个,那么只需运行git config core.autocrlf false - 提到这一点,因为通常 autocrlf 对于 windows 应该是 true 对于其他人来说应该是 input,但有时你需要特定于奇怪的边缘情况的东西。就我而言,我已经下载了一些文件并想记录我所做的更改,以便我可以记住我做了什么(而不是跟踪对代码的更改)。我不知道行尾是否重要(并且希望差异对“真实”的东西有意义)所以我禁用了 autocrlf。【参考方案2】:

来自gitattributes(5) Manual Page“效果”话题

text

此属性启用和控制行尾标准化。当一个 文本文件被规范化,它的行尾在 存储库。控制工作中使用的行尾样式 目录,对单个文件使用 eol 属性和 core.eol 所有文本文件的配置变量。

Set

在路径上设置文本属性可启用行尾规范化 并将路径标记为文本文件。发生行尾转换 无需猜测内容类型。

Unset 取消设置路径上的文本属性告诉 Git 不要 在签入或结帐时尝试任何行尾转换。

core.autocrlf 在新(1.7.2+)Git 中未使用,core.eol 和正确设置|取消设置文本属性被认为是更可靠的方式

【讨论】:

.gitattributes 文件中,我已经明确禁用了所有文本,对吧?另外,我没有看到它有一个选项可以让它不进行转换(尽管crlf 可能没有效果)? 经常混淆的重要事情 - 取消设置 text 并防止任何转换,您应该将 .gitattributes 设置为 * -text 而不是 * text=falsefalse 不是 text 属性的有效值 - git 不会识别它,而是会回退到其默认的 autocrlf 设置。此外,在更改 text 值后,您必须从本地存储库备份所有文件,进行提交,然后根据需要使用正确的行尾恢复文件,然后将它们提交回来。这样你的行尾就不会再被 git 修改了。【参考方案3】:

我想通了。似乎 SCP 程序正在转换行尾。当我尝试故意制作一个以 LF 结尾的文件然后观察它在下载时显示为 CRLF 时,我注意到了这一点。

因为这对我来说是解决方案,所以我接受这个答案,但未来的人也应该参考其他答案以获得更通用的解决方案。

【讨论】:

很好,比我的回答更具体。 +1【参考方案4】:

在您的项目中,应该有一个.gitattributes 文件。大多数时候,它应该如下所示(或screen-shot):

# Handle line endings automatically for files detected as text 
# and leave all files detected as binary untouched.
* text=auto

# Never modify line endings of our bash scripts
*.sh -crlf

#
# The above will handle all files NOT found below
#
# These files are text and should be normalized (Convert crlf => lf)
*.css           text
*.html          text
*.java          text
*.js            text
*.json          text
*.properties    text
*.txt           text
*.xml           text

# These files are binary and should be left untouched
# (binary is macro for -text -diff)
*.class         binary
*.jar           binary
*.gif           binary
*.jpg           binary
*.png           binary

* text=auto 更改为* text=false 以禁用自动处理(请参阅screen-shot)。

像这样:

如果您的项目没有 .gitattributes 文件,则行尾由您的 git 配置设置。要更改您的 git 配置,请执行以下操作:

进入该目录下的配置文件:

1) C:\ProgramData\Git\config

2) 在 Notepad++(或任何你喜欢的文本编辑器)中打开配置文件

3) 将“autocrlf=”更改为 false。

【讨论】:

为什么使用图片而不是代码标签?很不方便 因为我可以在图片中添加一个大红框来突出显示内容。 使用 * text=false 不会取消设置文本:它会将文本设置为字符串值 false。这与未指定文本(不是特别未设置)具有相同的效果。使用* -text 为其提供了特殊的未设置设置。取消设置路径上的文本属性告诉 git 在签入或签出时不要尝试任何行尾转换。 很抱歉,我不能对这个答案表示感谢。我花了半天时间才发现有人听从了误导性的建议。正如@JustAMartin 指出的* text=false 没有效果。请修正答案! 这个答案正确。正如下面@JustAMartin 和上述评论部分所指出的,您必须使用* -textnot * text=false。在这个答案确定之前,我已经投了反对票。请修正这个答案。【参考方案5】:

以下是您如何为单个 repo 执行此操作。

在 repo 的根目录下创建文件.gitattributes,并在其中包含这一行

* -text

就是这样。这是一个匹配所有文件的通配符,告诉 git 取消设置 text 属性。这意味着 git 将所有文件视为二进制文件,因此不执行任何行尾转换。

【讨论】:

以上是关于禁用 git EOL 转换的主要内容,如果未能解决你的问题,请参考以下文章

为什么dom4j文档对象将XML EOL r n转换为 n

禁止 git 自动转换换行符

如何防止 Git/Gitlab 修改 EOL 字符?

Git 索引和工作树 EOL 值与 .gitattributes 中设置的值不匹配

一次性更改多个文件的 EOL

电子邮件和 ftp 文本消息之间的大小差异 - EOL 字符?