TL;DR
这是三种可能的解决方案(不一定是only three).
-
Use:
git add --renormalize .
(在存储库的顶层完成一次)。这需要较新的 Git,但这是最简单的方法。
注意:我根本不清楚这是否会影响工作树版本;你可能还需要git checkout -- .
从索引重新复制到工作树。
- 对于每个文件
git status
正在抱怨:rm file; git checkout -- file
. The rm
删除工作树副本,以便git checkout
实际上必须根据新的行结束规则重新提取文件。
你可以稍微简化一下git rm -r .; git checkout HEAD -- .
(只有两个命令)但这会产生影响工作树中所有文件的副作用,甚至是任何不需要更改的文件(其中没有回车符的文件)。
- 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 行结尾,并且您将处于我们之前描述的状态。