你可以使用这个序列:
git rm -r .
git checkout -- .
请注意,这会破坏所有未提交的更改!
但是,您所说的问题敲响了警钟。
这些行尾修改(仅)在 index-to-work-tree 复制阶段执行。如果指示这样做,此阶段会将存储在索引中的仅 LF 行尾转换为存储在工作树中的 CR-LF 行尾。
其他行尾修改(仅)在工作树到索引复制阶段执行。如果指示这样做,此阶段会将存储在工作树中的 CR-LF 行结尾转换为存储在索引中的仅 LF 行结尾。
要理解所有这些,请注意:
这个东西被不同地称为索引,或暂存区,或(很少)缓存,拥有您的所有文件。好吧,暂时,在git rm -r . 之后,它有 no 文件,但我们会将它们全部放回下一个命令中。一般来说,它有每个文件的副本,准备好进入下一次提交。
工作树,或工作树或这个名称的一些变体,也拥有每个文件的副本。你的工作树也可以有额外的文件,Git 称之为 untracked 文件。部分或全部这些未跟踪的文件可能会被忽略。 (不会忽略跟踪的文件。当且仅当文件存在于索引中时才会跟踪文件。)
Git 从索引中的任何内容进行新的提交。工作树副本在这里并不重要。
您无法查看索引中的内容——不能直接查看。存储在索引(和提交)中的文件采用特殊的、只读的、仅限 Git 的冻结格式。您可以使用git ls-files(添加--stage 以获取详细信息)获取索引中所有文件的列表,但这很少有用。
您可以看到的是工作树中的文件。它们已从冷冻版本中提取出来,按原样重新水化,然后变成普通文件。您的所有计算机程序都可以处理它们,因为它们只是您计算机喜欢的任何格式的普通旧文件。你可以为他们做任何你喜欢的事情。
Git 必须在索引(它们被冻干并准备提交的位置)和工作树之间复制文件。有时,复制的方向是从索引到工作树。这时,Git 可以将 LF-only 变成 CR-LF。其他时候,复制的方向是从工作树到索引。此时,Git 可以将 CR-LF 变成 LF-only。
尽管选项很多,但这两个转换是 Git 唯一的行尾转换。各种选项都是告诉Git 的不同方式什么时候做,什么时候不做。
这是您问题中的警钟:
我有一个 repo,其中包含一个错误地以 LF 行结尾提交的文件。
就 Git 而言,只有 LF 的行尾是好。它们是文件的自然状态。所以以这种方式提交文件不是错误——反正对 Git 来说也不是。
如果您希望此类文件在它们是普通文件时具有 CR-LF 结尾(而不是冻干的仅 Git 内部 Git 文件),那也可以:您告诉 Git 请对 CR-执行 LF-only LF 在提取过程中 并且它做到了。您还可以在git add 期间告诉 Git 请 CR-LF 到 LF-only,它也这样做了,并且您的文件在冻干时继续是 LF-only,但 CR-LF 时可见、可用、可编辑等。
如果您希望 Git 永远不会弄乱您的文件——让它们以 CR-LF 行结尾即使在冻干时——也可以。但 Git 就是要永远存储数据。这些冻结的副本无法更改。存储在所有现有提交中的所有冻干、只读、Git 化版本将永远是 LF-only。如果您将这些仅 LF 文件与冻干 CR-LF 文件进行比较,每一行都会有所不同。
(是可以获取所有旧提交,将它们转换为具有 CR-LF 结尾的更新不同提交,并丢弃所有旧提交并强制每个人都可以从旧的提交切换到新的提交。有时这是要走的路。有时不是。你必须自己做出这个决定。)