我在Windows上,并且拥有系统范围的core.autocrlf=true
。
对于特定的存储库,我已经在本地将其覆盖为false
。
但这并没有转换检出文件中的行尾。我该怎么办?
dos2unix
,它们显示为已更改。git checkout --force HEAD
,但没有效果。我发现的唯一工作方法是删除所有文件,然后删除git reset --hard
,这很尴尬(=没有简单可靠的命令来执行此操作,并且它执行了许多不必要的工作-一切都是从头开始重新创建,而不仅仅是覆盖需要转换的文件。
答案 0 :(得分:1)
这是三种可能的解决方案(不一定是 only 三种)。
使用:
git add --renormalize .
(在存储库的顶层完成一次)。这需要更新的Git,但这是最简单的方法。
注意:尚不清楚这是否影响工作树版本;您可能仍然需要git checkout -- .
从索引重新复制到工作树。
对于git status
抱怨的每个文件:rm file; git checkout -- file
。 rm
删除了工作树副本,因此git checkout
实际上必须根据新的行尾规则重新提取文件。
您可以使用git rm -r .; git checkout HEAD -- .
(仅两个命令)来简化此操作,但这会产生副作用,即触摸工作树中的所有文件,甚至包括不需要更改的任何文件(不带回车符的文件,返回它们。)
像往常一样使用dos2unix
,然后在文件(或git add
)上运行.
。尽管出现了,但这应该使索引保持不变。
此后,在所有情况下,git status
应该说nothing to commit, working tree clean
。
这不是相当与Git: how to renormalize line endings in all files in all revisions?的重复,因为您不想重新复制一堆现有的提交。但是,git add --renormalize
的答案应该可以解决。
如果失败,您可以尝试PetSerAl's comment answer。
或者,如果失败,或者您的Git太旧而无法使用--renormalize
选项:
如果我使用例如
dos2unix
,它们显示为已更改。
您可以手动转换文件,然后git add .
,或删除工作树副本并再次git checkout
。 git checkout --force HEAD
之所以失败,是因为Git出于自身的利益太聪明了:它(错误地)看到工作树副本已经正确,并且避免对其进行操作。
每个文件始终有三个活动副本。假设您有一个README.txt
和一个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
和{{ 1}},依此类推。您已经将它们设置为将LF更改为CRLF,因此您的工作树中的副本目前具有CRLF结尾。
现在(在结帐后 之后),您更改您的设置,这样,被结帐的文件将具有仅LF的行尾,或保留其中的行尾。指数。不幸的是,文件的每个索引副本中的一项是关于工作树副本的信息。这使得Git 假定工作树副本与索引副本相同。
很显然,由于工作树副本具有CRLF结尾,而索引副本具有仅LF结尾,因此两者是不同的。但是,如果您没有更改行尾设置,则要求core.eol
否则,因此必须进行此假设。
如果您没有更改EOL设置,git status
不会说什么,这不会打扰任何人,因为如果您在git status
上运行git add
,则会复制工作树复制回索引。这样一来,这会将CRLF行尾转换为仅LF行尾,并重新压缩文件。生成的文件将与README.txt
副本匹配,而HEAD
则无需说什么。
但是您没有更改了EOL设置,因此,如果您现在运行git status
,Git应该将CRLF结尾复制到索引中。本质上,git add
被愚弄了:索引是故意说的-工作树副本匹配(即使不匹配),并且在工作树副本具有CRLF时运行git status
行尾会更改索引副本。
如果您在文件上使用git add
来更改工作树副本,Git现在会看到工作树副本的统计信息与索引的已保存“此文件是干净的”统计信息不匹配。也就是说,dos2unix
仍然被愚弄,但是现在说工作树副本是不同的!如果您git status
现在现在文件,则Git在更新索引副本时将保留仅LF行尾。最终结果将是索引副本与git add
副本完全匹配,和 Git更新文件的缓存工作树统计信息关于,以便它知道索引副本与工作树副本匹配。
基本上,在HEAD
和/或.gitattributes
变量中更改行尾设置后,必须让Git修复索引的“干净/脏”缓存数据。在core.*
之前,唯一的方法就是强制Git从索引复制到工作树:
git add --renormalize
或强制Git从工作树复制到索引:
rm worktreefile
git checkout -- worktreefile
这两种方法都可以修复索引的缓存数据,但是显然在此过程中还会造成一些额外的暴力行为。
git add worktreefile
副本的结尾为CRLF,则情况会发生变化假定HEAD
的提交副本具有CRLF结尾。然后,最初:
README.txt
副本匹配,因此具有CRLF结尾; HEAD
和索引都不同。这是真的,无论是否HEAD
被愚弄。
一旦您将工作树的仅LF行尾复制到索引中,以便索引也具有仅LF行尾,则 now 索引副本(“暂存为提交”)与git status
副本。此时,如果您进行 new 提交,则该提交将仅具有LF行尾,并且您将处于我们先前所述的状态。