TL;DR
创建过滤器驱动程序 plus.gitattributes
: 创建一个污迹过滤器运行的tr '\n' '\r'
and a 清洁过滤器运行的tr '\r' '\n'
,并将有问题的文件标记为使用此过滤器。使用仅 LF 行结尾将文件存储在 Git 中。 (过滤器驱动程序定义在.git/config
or $HOME/.gitconfig
文件和文件的名称或名称模式进入.gitattributes
.)
Long
正如您所看到的,Git 强烈喜欢以换行符结尾的行。 (它可以使用换行符分隔的行,其中最后一行缺少终止符,但这意味着添加一行会导致对前一个最终行的更改,因为它现在有一个换行符终止符,而新的最终行丢失换行符。)这对于单个快照并不重要,但对于生成有用的差异很重要。
现代 MacOS 和其他操作系统一样使用换行符。只有古老的向后兼容格式才有仅 CR 的行结尾。参见,例如,此 SuperUser Stack Exchange 网站发布.
Git 没有built in用于转换为此类行结尾或从此类行结尾转换的过滤器。 gitdoes然而,有一个通用机制用于更改工作树文件。
请记住,当 Git 在快照中存储任何文件时,该文件由 Git 所谓的斑点对象,它以一种特殊的、压缩的(有时是高度压缩的)、仅限 Git 的形式在内部存储。这个表格没有任何用处butGit,因此当您以有用的形式获取文件时 - 通过git checkout
例如,Git 将它们扩展为计算机常用的形式。同时,每当您获取像这样的普通文件并将其转换为仅限 Git 的形式时,Git 都会将该文件压缩为其仅限 Git 的形式。每当你将文件复制回 Git 时就会发生这种情况index using git add
.
当工作树就位时,每个文件的索引副本都存在,就像提交的副本一样。索引副本采用相同的仅 Git 格式。这里的主要区别是提交的副本can't被改变,但是索引副本can被改变。跑步git commit
拍摄索引中所有内容的快照就在那时,并将其作为新提交的新快照。因此该指数的作用为下一次提交会发生什么。使用git checkout
,您复制一些现有的提交into索引,并让 Git 将其扩展到工作树中;然后使用git add
,您可以有选择地用已更改的工作树文件的压缩版本替换特定索引副本。
这种在索引和工作树之间的复制是进行 Windows 风格的 LF 到 CRLF 转换的理想点,反之亦然,所以这就是 Git 所做的事情。如果你有一些other要执行的转换,不是直接内置于 Git 中,这是您告诉 Git 执行此操作的地方。
涂抹并清洁过滤器
A 污迹过滤器是 Git 将文件从压缩索引副本转换为工作树副本时应用的一种。在这里,如果您选择将换行符替换为 CRLF Windows 样式的行结束符或分隔符,Git 有一个内部转换器可以执行此操作:eol=crlf
. A 清洁过滤器Got 是在将文件从未压缩的工作树副本转换为压缩索引副本时应用的;又是在这里,eol=crlf
指示 Git 进行向后转换。
如果您想用仅 CR 替换换行符,则必须发明自己的转换器。假设您调用整个流程convert-cr
:
*.csv filter=convert-cr
(代替*.csv eol=crlf
)。这条线进入.gitattributes
(这是一个可提交的文件,您应该提交它)。
现在您必须定义convert-cr
筛选。这是一个 Git 配置文件,在这里我们发现了一个小缺陷:配置文件不可提交。这是一个安全问题:Git 将在此处运行任意命令,如果我可以提交此文件并克隆它,您将运行命令I指定,而没有机会先审查它们。所以你必须把它放入你的.git/config
你自己,或者进入你的全局配置(git config --global --edit
例如):
[filter "convert-cr"]
clean = tr '\r' '\n'
smudge = tr '\n' '\r'
现在每当 Git 转换时from仅限 Git 的格式,它会将换行符转换为 CR,并且每当 Git 转换时to仅 Git 格式,它将把 CR 转换为换行符。
这对现有存储的文件没有帮助
您今天拥有的任何现有快照\r
在它们内部,永远以这种方式存储。 Git 永远不会更改任何现有的存储文件!存储的数据宝贵且不可侵犯。您对此无能为力。嗯,有almost什么都没有:您可以完全丢弃这些提交,转而使用新的和改进的提交。但这是相当痛苦的:每次提交都会记住它的parent提交,因此如果您替换存储库中的早期提交,则必须替换every孩子、孙子等等,以便他们都记住这个新的提交序列。 (git filter-branch
做这项工作。)
但是,您可以指导 Git 如何diff现有提交中的特定文件,也使用.gitattributes
and 差异驱动程序。有多种方法可以做到这一点,但最简单的方法是定义一个textconv属性,它将“二进制”文件(例如其存储版本可能仅包含 CR 字符的文件)转换为文本(面向行,即基于换行符)文件。这里使用的 textconv 过滤器与污迹过滤器完全相同。
有关更多详细信息,请参阅gitattributes 文档.