更改行尾 git 配置

Change End Of Line git configuration

所以现在我在另一所大学的项目中工作,他使用 mac,我使用 windows,所以我们遇到了 EOL(行尾)问题文件。我们决定,我们希望所有文件都是 LF。对他来说这没问题,因为他使用的是 mac,但我必须将所有文件从 CRLF 更改为 LF,这我已经完成了,我还设置了一个配置,每当我添加一个新文件时,它都以 LF 开头。问题是当我想提交对我们的 repo 的更改时,它会给我这个警告。

The file will have its original line endings in your working directory warning: LF will be replaced by 
CRLF in tsconfig.build.json.

我想达到什么目的?我想通过 github 禁用此“自动”替换。我不希望我的文件被 CRLF 替换,我希望我所有的文件始终是 LF。有什么建议吗?

首先是一些重要的术语说明:GitHub 永远不会取代 anything。他们真的不能。不用担心 GitHub 在这里;他们是无关紧要的。 担心 你自己的 Git,除了以相同的三个字母开头外,与 Git枢纽。 GitHub 是一个 托管服务提供商,您可以在其中存储和访问 Git 存储库。 Git 是实现版本控制系统的软件。

你的Git就是问题所在and/or应该解决了。那么,您的 Git 以及您朋友或同事的 Git,等等,具体取决于他们使用的系统。您的文件编辑器也可以发挥作用,但是 Git 可以并且将会覆盖它们,如果您将其设置为这样做的话。

i want all my files to be LF at all times.

您提到了 Visual Studio 代码,它可能也有自己的处理文件的方法。如果适合您的目的,您可以对此进行调查和配置。此答案仅涉及 Git 本身。

.gitattributes中设置什么

为确保新添加或更新的文件获得并查看仅 LF 行结尾,请修改现有 .gitattributes 文件以列出您想要影响的文件名或模式,包括:

<pattern> text eol=lf

这里的 pattern 部分可以包括 *.json*.sh 甚至只是 * (匹配所有文件名)。

如果您没有 .gitattributes 文件,请创建一个。确保它包含纯文本,最好是没有字节顺序标记的简单 ASCII 或 UTF-8。

* text eol=lf 行是什么意思

如上所述,第一部分是一个模式:它是该行其余部分适用的一组文件。通过包含多行,您可以列出多个模式,或多次列出相同的模式。 last 匹配模式通常会覆盖较早的匹配模式。1

text 部分告诉 Git 这个文件是 text,即由行组成的可编辑内容,而不是二进制文件, Git 不能假定包含文本。这会在文件上启用 行尾转换2

eol=lf 告诉 Git 行的结尾应该是什么样子lf 这里的意思是 使用换行符结尾 ,而不是 Windows 程序似乎更喜欢或需要的 CRLF 行结尾。

您可以为 eol 设置的另一个值是 eol=crlf,但根据您上面的陈述,您不希望这样。


1.gitignore中也是如此。但是,在 .gitattributes 文件中,这会变得复杂,因为每一行都可以设置不同的东西。例如,你可以这样写:

* text
*.bin -text

-text 覆盖 text,因此最后一行优先,但 仅适用于名称以 .bin 结尾的文件。但你也可以这样写:

* text zorg
*.bin -text

那么您已经为 所有 文件(包括 *.bin 文件)设置了 zorg 属性。 -text 取消设置 text *.bin,但保留 zorg 设置。

2从技术上讲,如果您使用 eol=lf 部分,则可以完全省略 text 部分。将 eol 设置为某个值意味着设置 textThe gitattributes documentation 在示例中使用了 text eol=lf,因此这似乎是 de rigueur.


不要使用core.autocrlf

非常旧的 Git 版本使用 core.autocrlfcore.eol 和其他类似的 core 设置来执行此类操作。除此之外,您可以(但不应该)在 .gitattributes 行中使用 text=auto。这告诉 Git 猜测 文件是否包含文本,因此是否包含行尾可以更改的行,或二进制(因此不应将其行尾弄乱,因为它们只是巧合地 类似于 行尾,但实际上是宝贵的二进制数据)。

您看到的警告与此内容有关。如果 Git 计划破坏某些文件,而 方式 Git 计划破坏文件在 Git 看来有点可疑,Git 警告你。

底层机制

可能有一天——或者可能已经到了——您想要查看存储库本身中的内容,而不是您使用的文件。您可能想知道此声明的含义。毕竟,存储库不是您使用的文件的集合吗?但答案是:不,不是!

Git 都是关于提交的。 Git 存储库包含和使用的是,至少在大多数情况下,提交。虽然提交 包含 文件,但提交本身不是文件,也不是它包含的文件。提交是它自己的事情。这是真实的东西,它是一个单位——嗯,主要是 单位——你的 Git 传递给其他 Git,反之亦然。

每个提交都有一个唯一的编号。这不是 您的 存储库中的唯一编号,而是全球或普遍唯一的编号:UUID or GUID。为了确保每个 ID 对于每个特定的提交都是真正唯一的,Git 为提交分配了非常长且看起来随机的哈希 ID。实际上,这些是每个提交的真实名称。您的 Git 与其他一些 Git 聚在一起,并且这两个共享提交通过共享这些 ID。如果你的 Git 有一些他们没有的 ID,那就意味着你的 Git 有一些他们没有的 commit,反之亦然。

这个 ID 实际上是所有进入提交的数据的加密校验和。因此,一旦提交,任何 提交的任何部分都不能永远更改。这就是为什么您不必担心 GitHub。你在你的计算机上进行提交,从那时起,没有任何东西——甚至 Git 本身——都不能 改变 它们。它们是完全、完全只读的。任何提交内的任何文件内的任何行结尾都是 forever——连同该行的其余部分,以及该文件中的所有其他行。每次提交中的文件都被永久冻结。

因此,提交包含文件(实际上是它的主要数据)以及我们不会在此答案中讨论的其他一些 元数据 。提交中的文件与元数据一起被永久冻结。它们还以去重格式存储,只有 Git 本身可以 读取 。这两个因素使文件对于完成任何实际工作毫无用处,因为:

  • 我们需要能够读取文件(在程序中,在我们的编辑器中,等等),并且
  • 我们需要能够更改 文件,以进行新的工作。

这意味着要使用某个提交的文件,Git 必须提取 文件。当它这样做时,它会将提取的文件放在工作区中。 Git 将此工作区称为您的 工作树 工作树 。这很简单:这是您工作的地方。

您在工作树中处理的文件不是 Git 的 文件。提交的文件在一些提交中。那些是无法改变的。 Git的文件在别处。工作树文件是你的,根本不在Git里面。

因为 Git 必须提取文件 才能看到并使用它们,这是一个理想的地方来获取只有 LF 行结尾的文件,并将它们变成以 CRLF 结尾的文件,供您查看和使用 on/with。如果您选择 Git 乱用行尾,Git 将始终尝试存储只有 LF 行尾的文件,并在提取过程中将它们转换为 CRLF 尾。

因为 Git 必须先将文件压缩成冻结格式,然后才能将任何 新的或更改的文件 放入提交,这是获取具有 CRLF 行结尾的文件的理想位置,并将它们转换为具有 LF-only 行结尾的文件,然后再将它们存储在新的提交中。如果您选择 Git 乱用行尾,Git 将在用新内容替换文件内容时始终将这些行转换为仅 LF 行。

此机制适用于整个文件。当您使用 git add 时——如果您更新了某些文件,则必须这样做 3—Git届时会做行尾转换将文件压缩成冻结格式,准备提交。4 同样,当您使用 git checkout 从一个提交切换到另一个提交时,Git 必须 从您的工作树中删除 任何在您要切换 的新提交中不同(或完全消失!)的文件,并将其替换为从该提交中取出的文件。然后它将提交的文件扩展为您的工作树中可用的文件,并且在这样做的同时,可以用 CRLF 行结尾替换 LF-only 行结尾。

其中特别棘手的部分是,如脚注 4 中所述,Git 努力不去理会 没有 更改的文件。这一切 假设 无论 eol= 之前可能应用的设置,现在仍然适用。因此,有时,当您 更改 eol= 设置时,您必须删除 Git 的索引以使其无效,或者触摸您工作中的所有文件-树,或使用 git add --renormalize,如果您的 Git 足够新,可以使用“重新规范化”选项。

这在实践中归结为,如果您 更改 eol= 设置,您可能需要 运行 git add --renormalize --all 或相似的。如果你没有它,有一些相当丑陋的解决方法,但最好的办法可能是升级你的 Git 版本。


3虽然您可以使用git commit -agit commit --include和文件名列表,但是这在内部工作或多或少是对这些文件的 运行 git add或多或少 部分内容很多,但此答案不会详细介绍这些细节。

4this 的机制涉及 Git 不同的调用,index,或者暂存区,或者——现在很少见——缓存。这三个术语都指的是同一件事。这个东西的缓存方面试图跟踪您可能在工作树中实际更改了哪些文件,以及您肯定没有在工作树中更改的文件。这让 Git 不理会这些文件,因为您从一个提交更改到另一个提交,从而加快了 Git 的速度。它还允许 git add 跳过 添加一些文件,加速 Git。