让Git在"<<<<<<< HEAD"合并行上使用CRLF

11

是否有可能要求Git在需要合并文件时将行末的LF改为CRLF?

Merge using LFs

如果在没有可见EOL字符的文本编辑器中解决冲突时,如果通过选择删除,很容易出现这些LF被合并的情况:

Delete by selection

这将使您的文件中出现两个LF,而文件通常应该是CRLF。

显然,一种替代方法是在解决合并冲突时更加注意行结尾,但我想询问一下是否有一种方法告诉Git在这里生成行时使用CRLF。


你没有告诉我们任何关于你的环境的信息。你用的是什么操作系统?如果是Windows,你使用的是哪个Git发行版?是Git for Windows还是Cygwin Git或者某个集成Git的第三方产品?版本是多少?有哪些与EOL相关的Git设置生效? - kostix
1
我认为这并不重要。我只是问:“当Git需要合并文件时,是否可以要求Git使用CRLF而不仅仅是LF来结束行?”值得一提的是,我正在Windows上使用Cygwin Git。目前我的autocrlf设置为false。 - Jamie Humphries
你低估了Git处理EOL问题所需要应对的复杂性。快速查看git-config手册页面或在SO上搜索“git+cr+lf”即可了解。而且,不同软件平台之间存在阻抗不匹配(例如,Git for Windows实现了很多怪癖以使其在Windows上正常运行),这可能会影响Git的工作方式。 - kostix
从git 2.8+(2016年3月)开始,这个问题不会再发生了。请参见下面的我的答案 - VonC
3个回答

11
“当Git需要合并文件时,是否有可能要求Git在将行放入文件末尾时使用CRLF而不仅仅是LF?”
“实际上是可以的,从git 2.7.2+ (2016年2月)开始。”
“而且你不需要做任何事情。”

查看 提交 15980de, 提交 86efa21 (2016年1月27日) 由 Johannes Schindelin (dscho)完成。
(由Junio C Hamano -- gitster --提交ab2c107中合并,2016年2月17日)

merge-file: 让冲突标记与上下文的行尾风格匹配

当合并具有CR / LF行尾的文件时,冲突标记应该与其相匹配,否则输出文件将具有混合的行尾

这在Windows上特别重要,因为某些编辑器会对混合的行尾感到非常困惑。

Beat Bolli最初版本的补丁尊重了core.eol,而开发人员的后续改进也尊重了gitattributes
不过,这种方法并不是最佳的: git merge-file被发明成为GNU merge的替代品,因此它没有问题在任何存储库之外运行!

原始方法的另一个问题是由Junio Hamano指出的:遗留存储库可能已经使用CR / LF行尾提交了它们的文本文件(core.eolgitattributes会给我们一个错误的印象)。因此,更好的方法是如果可以,就简单地匹配上下文的行尾风格

实际上,我们根本不必查看整个上下文:

  • 如果所有文件都只有LF,或者它们都具有CR / LF行尾,则仅查看一个单独的行以匹配该风格就足够了。
  • 如果行尾已经混合了,那么仍然可以模拟一个单独行的行尾:我们只会增加混合行尾的数量,并且我们无法对此做任何事情。

因此,我们所做的是:我们查看冲突之前的行,如果它是最后一行并且没有换行符,则回退到之前的行,再回退到第一行,首先是第一张图像中的行,其次是第二张图像中的行,最后是预处理图像。
如果我们发现一致的CR / LF(或未决定),则匹配该行尾风格,否则,对于冲突标记,我们使用LF-only行尾。

请注意,虽然确实必须至少有两行可以查看(否则将没有冲突),但对于行尾来说并不是如此:这三个文件可能全部由没有任何行尾的单个行组成。在这种情况下,我们回退到仅使用LF-only。


3
在Git中,没有控制“<<<<”标记使用的行结尾的设置;它们在Git源代码中硬编码为使用'\n'(请参见 xmerge.c的第173行)。如果您将“eol”或“core.eol”设置为“crlf”,则文件中的“<<<<”标记将具有\r\n的行结尾(这发生在上述代码链接后的smudge/clean过滤器步骤中),但这会产生一个主要副作用:文件将在进入存储库时进行“规范化”,因此您将提交具有Unix行结尾的文件。对于像上面示例中的.Net项目,这可能不是您想要的结果。因此,我没有一个好的答案,抱歉。

感谢您提供源代码链接。看来我的问题的答案就是“不行”了 :) - Jamie Humphries
2
你可以向 Git 核心团队报告一个 Bug 吗? - Rich

1

我不确定是否有一种全局的方法来做到这一点,但是你可以在.gitattributes文件中为每个文件扩展名设置默认的EOL字符(请参阅gitattributes文档中的“换行符转换”部分)。

例如,在git项目根目录中编辑.gitattributes文件,使其包含类似以下内容:

*.cs         eol=crlf
*.config     eol=crlf

在我的实验中,这个方法可行,但它的副作用是在提交时重写文件内容为 Unix 的行结尾符。您知道有什么方法可以避免这种情况吗? - Rich

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