【问题标题】:Change End Of Line git configuration更改行尾 git 配置
【发布时间】:2020-12-23 12:20:30
【问题描述】:

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

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。有什么建议吗?

【问题讨论】:

    标签: git github visual-studio-code newline eol


    【解决方案1】:

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

    你的 Git 是问题所在和/或应该解决的地方。嗯,你的 Git,以及你朋友或同事的 Git,等等,这取决于他们使用什么系统。您的文件编辑器也可能扮演角色,但 Git 可以并且将覆盖它们,如果您设置它这样做的话。

    我希望我的所有文件始终都是 LF。

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

    .gitattributes中设置什么

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

    <pattern> text eol=lf
    

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

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

    * text eol=lf 行是什么意思

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

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

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

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


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

    * text
    *.bin -text
    

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

    * text zorg
    *.bin -text
    

    那么您已经为所有文件设置了zorg属性,包括*.bin文件。 -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 本身)可以更改它们。它们是完全、完全只读的。任何提交中的任何文件内的任何行结尾都是这种方式永远——连同该行的其余部分,以及该文件中的所有其他行。每次提交中的文件都被永久冻结。

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

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

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

    您在工作树中处理的文件不是 Git 的 文件。提交的文件在某个提交中。那些是不能改变的。 Git 的文件在别处。工作树文件是你的,根本不在 Git 中。

    因为 Git 必须先提取文件才能查看和使用它们,所以这是获取仅具有 LF 行结尾的文件并将其转换为 CRLF 结尾的文件的理想位置你看到和工作/与。如果您选择让 Git 乱用行尾,Git 将始终尝试以仅 LF 行尾存储文件,并在提取过程中将它们转换为 CRLF 结尾。

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

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

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

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


    3虽然您可以使用git commit -agit commit --include 和文件名列表,但其内部工作方式或多或少是运行@ 987654370@ 这些文件。 或多或少部分有很多内容,但此答案不会涉及这些细节。

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

    【讨论】:

      猜你喜欢
      • 2014-10-17
      • 2011-04-24
      • 1970-01-01
      • 2011-09-12
      • 1970-01-01
      • 2018-06-29
      • 2012-05-12
      • 1970-01-01
      相关资源
      最近更新 更多