更改 core.autocrlf 后如何强制转换工作树文件?

2023-11-23

我在 Windows 上并且有系统范围core.autocrlf=true.

对于特定的存储库,我已在本地覆盖它false.

但这并没有转换签出文件中的行结尾。我怎么做?

  • 如果我使用例如手动转换文件dos2unix,它们显示为已更改。
  • 也尝试过git checkout --force HEAD,没有效果。

我发现的唯一工作方法是删除所有文件,然后git reset --hard这是相当尴尬的(=没有简单可靠的命令来做到这一点,而且它做了很多不必要的工作——一切都是从头开始重新创建的,而不是仅仅覆盖需要转换的文件)。


TL;DR

这是三种可能的解决方案(不一定是only three).

  1. Use:

    git add --renormalize .
    

(在存储库的顶层完成一次)。这需要较新的 Git,但这是最简单的方法。

注意:我根本不清楚这是否会影响工作树版本;你可能还需要git checkout -- .从索引重新复制到工作树。

  1. 对于每个文件git status正在抱怨:rm file; git checkout -- file. The rm删除工作树副本,以便git checkout实际上必须根据新的行结束规则重新提取文件。

你可以稍微简化一下git rm -r .; git checkout HEAD -- .(只有两个命令)但这会产生影响工作树中所有文件的副作用,甚至是任何不需要更改的文件(其中没有回车符的文件)。

  1. Use dos2unix像你一样,然后运行git add在文件上(或在.)。尽管表面上看起来如此,但这应该会使指数保持不变。

在所有情况下,之后,git status应该说nothing to commit, working tree clean.

Long

这不是quite的副本Git:如何规范所有修订版中所有文件的行结尾?,因为您不想重新复制一堆现有的提交。但是,那git add --renormalize答案应该有效。

或者,如果失败或者你的 Git 太旧而无法使用--renormalize option:

如果我使用例如手动转换文件dos2unix,它们显示为已更改。

您可以手动转换文件,然后git add .,或删除工作树副本并git checkout又是他们。这git checkout --force HEAD失败是因为 Git 太聪明了:它(错误地)看到工作树副本已经正确并避免对其进行工作。

这里发生了什么

任何时候,都有,three每个文件的活动副本。假设你有一个README.txt and a prog.cc,两者在工作树中都有 CRLF 结尾,但在存储库中只有 LF 行结尾。

   HEAD          index       work-tree
----------    ----------    ----------
README.txt    README.txt    README.txt
prog.cc       prog.cc       prog.cc

提交中的副本是神圣不可侵犯的、不可侵犯的、以任何形式永久冻结(或只要该提交存在)。 (我现在假设每个文件都有 LF 样式的行结尾。)它也被压缩了。

副本在index是可写的,但最初与提交中的副本匹配。所以它也会有仅 LF 的行结尾。它也被压缩了(它实际上首先只是对已提交副本的引用)。

副本在工作树未压缩,并且具有您告诉 Git 通过您的命令使用的行结尾.gitattributes文件(无)和你的core.autocrlf and core.eol等等。你had他们设置将 LF 更改为 CRLF,因此工作树中的副本目前具有 CRLF 结尾。

Now—after结帐处——你change您的设置,以便签出的文件将仅具有 LF 行结尾,或者保留索引中的内容。不幸的是,文件的每个索引副本中的条目之一是信息about工作树副本。这使得 Gitassume工作树副本与索引副本相同。

显然,由于工作树副本具有 CRLF 结尾,而索引副本仅具有 LF 结尾,因此两者是不同的。但如果您没有更改行尾设置,git status is required反之,则必须做出这样的假设。

如果您没有更改 EOL 设置,git status不会说什么,这不会打扰任何人,因为如果你跑git add上,说,README.txt,这会将工作树副本复制回索引中。在此过程中,这会将 CRLF 行结尾转换为仅 LF 行结尾,并重新压缩文件。生成的文件将匹配HEAD复制,并且git status就不得不说什么了。

But you did更改 EOL 设置,因此如果您运行git add现在,Git 应该将 CRLF 结尾复制到索引中。本质上,git status被愚弄了:索引说——故意的!——工作树副本匹配(即使它不匹配),并且运行git add而工作树副本具有 CRLF 行结尾会更改索引副本。

如果你使用dos2unix在文件上更改工作树副本时,Git 现在发现工作树副本的统计信息与索引保存的“此文件是干净的”统计信息不匹配。那是,git status 仍然被愚弄但现在说工作树副本不同!如果你git add文件now,Git 将在更新索引副本时保留仅 LF 的行结尾。最终结果将是索引副本与HEAD毕竟复制andGit 更新缓存的工作树统计信息about文件,以便它知道索引副本与工作树副本匹配。

本质上,在更改行结束设置之后 -.gitattributes and/or core.*变量——您必须让 Git 修复索引的“干净/脏”缓存数据。直到git add --renormalize唯一的方法是强制 Git 从索引复制到工作树:

rm worktreefile
git checkout -- worktreefile

或者强制 Git 从工作树复制到索引:

git add worktreefile

两者都修复了索引的缓存数据,但显然在此过程中做了一些额外的暴力。

请注意,如果已提交HEAD副本有 CRLF 结尾,事情发生了变化

假设提交的副本README.txt有 CRLF 结尾。然后,最初:

  • 索引副本匹配HEAD像往常一样复制,所以它有 CRLF 结尾;
  • 在工作树中以 CRLF 结尾,所有三个副本都匹配;
  • 但是如果您在工作树中选择仅 LF 结尾并实现这一点,则工作树副本与两者都不同HEAD和索引。

无论是否git status被愚弄了。

将工作树的仅 LF 行结尾复制到索引中,以便索引也具有仅 LF 行结尾,now索引副本(“暂存以供提交”)与HEAD复制。此时,如果您创建一个new提交,该提交将具有仅 LF 行结尾,并且您将处于我们之前描述的状态。

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

更改 core.autocrlf 后如何强制转换工作树文件? 的相关文章

随机推荐