git 中的自定义行结尾(LF 和 CR+LF 除外)
Custom line-endings in git (other than LF and CR+LF)
我被聘为顾问,与一家大公司使用的糟糕内部 DSL 一起工作。
我说很糟糕,因为代码行不是用回车 returns 或换行符来结束每行代码,而是用五个字符的 ASCII 字符串 <EOL>
分隔。这些文件有数千 "lines" 长。任何嵌入的回车 returns 或换行符都会导致解释器崩溃。
我无法更改他们的解释器或语言,但我需要使用用这种语言编写的大量 (>100 MB) 代码库。
在对此代码进行任何更改之前,我想将其放入 git 存储库中以进行跟踪。有没有办法告诉 git 字符串 <EOL>
代表行尾,就像您可以用 core.eol=lf
指定 LF
或 CR+LF
一样?例如,core.eol="<EOL>"
。如果是这样,这将使我的生活在两个方面变得更轻松:
- 它将使合并和差异智能地工作; git 会知道 "lines" 在哪里。
- 我可以(例如)签入以
<EOL>
作为行尾的原始代码,然后在另一台设置了 core.eol=lf
的机器上签出,然后 git 将转换自动来回。 (我可以使用常规文本编辑器和常规工具!)
我确实认识到这是一个小众的边缘案例。我也明白我可以添加一个中间处理步骤来在与 git 交互之前来回转换,但我想避免这种情况,除非绝对必要,因为我更愿意将他们现有的代码库直接导入 git ] 无需先对其进行预处理。
如果此功能不可用,我什至更愿意创建 git 的自定义版本而不是添加额外的处理步骤,所以如果有人知道其中可能涉及哪些复杂性,我会很感兴趣在了解这些。
此自定义过滤器设置将导致 *.dsl
个文件在 Git 存储中包含 <EOL>
,但在您的工作目录中检出时 \n
。 git diff
等工具将在签出版本(例如 \n
)上运行。那是你想要的吗?
~/.gitconfig
或 .git/config
[filter "crazy-eol"]
clean = awk 'BEGIN{ORS="<EOL>"}1'
smudge = awk 'BEGIN{RS="<EOL>"}1'
[diff "crazy-eol"]
textconv = awk 'BEGIN{RS="<EOL>"}1'
.gitattributes
或 .git/info/attributes
*.dsl filter=crazy-eol diff=crazy-eol
有一种方法可以做到这一点。这一点都不方便,如果文字字符串 <EOL>
确实 出现在一行中,则 运行 存在进行不可逆更改的风险(尽管根据您对 DSL 的描述,这似乎不可能发生。
不过,您不能使用 core.eol
设置。您将需要使用 smudge 和 clean 过滤器。查看the gitattributes documentation中的描述。您的两个过滤器会将 <EOL>
转换为换行,反之亦然。事实上,这正是 core.eol
和 core.autocrlf
以及 text
转换过滤器所做的:它们在一个或另一个方向上用 \n
替换 \r\n
,只是正如您在一个方向或另一个方向将 <EOL>
替换为 \n
一样。事实上,如果你进一步查看文档,在 "Interaction between checkin/checkout attributes" 部分,你会看到 Git 只是有一个 text
过滤器,它的作用就像一个干净的 and/or 涂抹过滤器,作为管道的一部分。
在你做任何这些之前,考虑...
在你为此烦恼之前,考虑一下你自己的一次性传球。一旦你有了 "normal" 形式的文件,你就可以 Git-ize 那些。在处理这些文件之前,您总是可以 运行 您自己的消毒剂。然后,一旦你准备好文件,你 运行 他们通过 "insanitizer" 回到疯狂的 <EOL>
格式,完全在 Git 之外。
我认为这个(外部 sanitizer/insanitizer)会更容易使用,真的。
我被聘为顾问,与一家大公司使用的糟糕内部 DSL 一起工作。
我说很糟糕,因为代码行不是用回车 returns 或换行符来结束每行代码,而是用五个字符的 ASCII 字符串 <EOL>
分隔。这些文件有数千 "lines" 长。任何嵌入的回车 returns 或换行符都会导致解释器崩溃。
我无法更改他们的解释器或语言,但我需要使用用这种语言编写的大量 (>100 MB) 代码库。
在对此代码进行任何更改之前,我想将其放入 git 存储库中以进行跟踪。有没有办法告诉 git 字符串 <EOL>
代表行尾,就像您可以用 core.eol=lf
指定 LF
或 CR+LF
一样?例如,core.eol="<EOL>"
。如果是这样,这将使我的生活在两个方面变得更轻松:
- 它将使合并和差异智能地工作; git 会知道 "lines" 在哪里。
- 我可以(例如)签入以
<EOL>
作为行尾的原始代码,然后在另一台设置了core.eol=lf
的机器上签出,然后 git 将转换自动来回。 (我可以使用常规文本编辑器和常规工具!)
我确实认识到这是一个小众的边缘案例。我也明白我可以添加一个中间处理步骤来在与 git 交互之前来回转换,但我想避免这种情况,除非绝对必要,因为我更愿意将他们现有的代码库直接导入 git ] 无需先对其进行预处理。
如果此功能不可用,我什至更愿意创建 git 的自定义版本而不是添加额外的处理步骤,所以如果有人知道其中可能涉及哪些复杂性,我会很感兴趣在了解这些。
此自定义过滤器设置将导致 *.dsl
个文件在 Git 存储中包含 <EOL>
,但在您的工作目录中检出时 \n
。 git diff
等工具将在签出版本(例如 \n
)上运行。那是你想要的吗?
~/.gitconfig
或 .git/config
[filter "crazy-eol"]
clean = awk 'BEGIN{ORS="<EOL>"}1'
smudge = awk 'BEGIN{RS="<EOL>"}1'
[diff "crazy-eol"]
textconv = awk 'BEGIN{RS="<EOL>"}1'
.gitattributes
或 .git/info/attributes
*.dsl filter=crazy-eol diff=crazy-eol
有一种方法可以做到这一点。这一点都不方便,如果文字字符串 <EOL>
确实 出现在一行中,则 运行 存在进行不可逆更改的风险(尽管根据您对 DSL 的描述,这似乎不可能发生。
不过,您不能使用 core.eol
设置。您将需要使用 smudge 和 clean 过滤器。查看the gitattributes documentation中的描述。您的两个过滤器会将 <EOL>
转换为换行,反之亦然。事实上,这正是 core.eol
和 core.autocrlf
以及 text
转换过滤器所做的:它们在一个或另一个方向上用 \n
替换 \r\n
,只是正如您在一个方向或另一个方向将 <EOL>
替换为 \n
一样。事实上,如果你进一步查看文档,在 "Interaction between checkin/checkout attributes" 部分,你会看到 Git 只是有一个 text
过滤器,它的作用就像一个干净的 and/or 涂抹过滤器,作为管道的一部分。
在你做任何这些之前,考虑...
在你为此烦恼之前,考虑一下你自己的一次性传球。一旦你有了 "normal" 形式的文件,你就可以 Git-ize 那些。在处理这些文件之前,您总是可以 运行 您自己的消毒剂。然后,一旦你准备好文件,你 运行 他们通过 "insanitizer" 回到疯狂的 <EOL>
格式,完全在 Git 之外。
我认为这个(外部 sanitizer/insanitizer)会更容易使用,真的。