在与使用不同操作系统的人一起工作时,我遇到了由于行尾导致的 merge 冲突问题。我在 Windows 上工作,而我的同事在 Mac 上工作。当他推送他的更改时,有时他没有处理的文件会在 diff 中显示为已更改,因为行结尾现在显示 ^M
在每个文件上。这导致了 merge 冲突。我在 Git 文档中阅读了以下内容:
Git can handle this by auto-converting CRLF line endings into LF when you add a file to the index, and vice versa when it checks out code onto your filesystem. You can turn on this functionality with the core.autocrlf setting. If you’re on a Windows machine, set it to true — this converts LF endings into CRLF when you check out code:
$ git config --global core.autocrlf true If you’re on a Linux or macOS system that uses LF line endings, then you don’t want Git to automatically convert them when you check out files; however, if a file with CRLF endings accidentally gets introduced, then you may want Git to fix it. You can tell Git to convert CRLF to LF on commit but not the other way around by setting core.autocrlf to input:
$ git config --global core.autocrlf input This setup should leave you with CRLF endings in Windows checkouts, but LF endings on macOS and Linux systems and in the repository.
这是有道理的,但我仍然不清楚这些文件是如何实际提交到 repo 协议(protocol)中的。例如,如果他在他的系统上创建了一个文件,它将包含所有 LF
行尾,对吗?因此,当他提交时,我认为这些行结尾将按原样保留。当我 pull 时,我的 autocrlf
正在true
将使用 CRLF
检查它们据我了解,行结尾。 (我收到警告 warning: LF will be replaced by CRLF in <file x>; The file will have its original line endings in your working directory
)
关于此的几个问题:当警告说“工作目录”时,它指的是什么?此外,当我随后进行更改或创建其他文件时,所有这些文件都有 CRLF
行尾和 commit+push,它们是否作为 CRLF
存储在 repo 中?或 LF
?
我想理想的是让 repo 剥离除 LF
之外的任何东西每次提交;这是怎么回事?引擎盖下发生了什么,我们如何才能强制其行为一致?
最佳答案
Q1 Enforcing consistent lineendings
Q2 Enforcing at commit as well as checkout (comment)
我将把它分成两部分:实践和原则
练习
- 严格避免
autocrlf
— 查看原因 autocrlf is always wrong . 和 here对于核心 git 开发人员争论 autocrlf 的考虑不周。请特别注意,实现者对批评感到恼火,但并不否认批评。 - 虔诚地使用
.gitattributes
代替 - 使用
safecrlf=true
强制提交清洁。safecrlf
是您 Q2 的答案——一个在 checkin checkout 往返过程中会更改的文件会在 checkin 阶段本身出错。
当一个新的 repo 被初始化时:
通过 ls -lR
并选择它的类型 text, binary
或忽略(即把它放在 .gitignore 中)
调试:
使用 git-check-attr检查属性匹配和计算是否符合要求
原则
数据存储
我们可以将 git 视为数据存储,大致类似于 USB 驱动器。
如果我们放入的东西输出相同,我们就说驱动器工作正常。否则它已损坏。同样,如果我们提交的文件在 checkout 时出现相同,则 repo 很好,否则(某些东西)很无聊。关键问题是
“相同”是什么意思?
这很重要,因为我们在不同的上下文中隐含地应用了不同的“相同性”标准!
二进制文件
- 二进制文件是字节序列
- 忠实地保留该序列相当于复制文件
文本文件
...不同
文本文件由一系列“可打印字符”组成——让我们不指定可打印字符的概念,只是说no cr no lf!
这些行如何分隔(或终止)同样未指定
象征性地:
输入 Line = [Char]
输入文件 = [行]在 1st unspecified 展开给我们 ASCII、Latins、Unicode 等等...与这个问题无关
扩展2号是windows *nix等的区别 JFTR this kind of 文件可能鲜为人知,但也存在。记住“线条序列”的概念可以在许多不同的层次上应用是特别有用的。
我们不关心相同性如何尊重未指定的部分
回到我们的
USB 驱动类比
当我将 foo.txt 从 Windows 复制到 Linux 时,我希望内容是不变的。但是,如果 H:foo.txt
更改为 /media/name/Transcend/foo.txt
,我会非常满意。事实上,如果 windowsisms 未经翻译通过,反之亦然,那就有点烦人了。
牵强附会?? ¡¡Think again!!
感谢像 Theodore T 这样杰出的人,所以我们认为 Linux 可以读取 Windows 文件(系统)是理所当然的。发生这种情况是因为
- 抽象匹配
- 抽象 stash
发生在幕后。
回到 Git
因此,我们希望 checkin git 的文件与 checkout 的文件相同......在不同的时间......和操作系统!
要注意的是,相同的概念非常重要,因此 git 需要我们的一些帮助来实现令我们满意的“相同”......这种帮助称为 .gitattributes
!
关于windows - 如何在具有跨平台兼容性的 Git 提交中强制执行一致的行结尾,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/57960566/