git - 在所有提交中将 CRLF 替换为 LF

标签 git

我正在尝试在所有提交中将 CRLF(windows 行结尾)替换为 LF(unix 行结尾)。

我发现你可以使用这个配置:

git config --global core.autocrlf input

但根据我的理解,这将在未来的提交中用 LF 替换 CRLF,而不是在我的存储库中已有的提交中。

最佳答案

可以更改您的存储库中的历史记录,以便看起来始终使用 LF;但这不是一个简单的过程,并且需要付出一定的成本(这可能重要也可能不重要,具体取决于您的存储库的使用方式)。您可能想仔细看看为什么您希望所有提交都具有 LF,并看看是否有更简单的方法来获得您想要的结果。

(例如,如果您正在使用一个使用 LF 行结尾的系统,并且只想在每次 checkout 文件时都将文件规范化为该标准,那么您也许可以使用过滤器来实现这一点 - 这基本上是相同的想法就像当存储库包含(至少一些)LF行结尾时 autocrlf 对 Windows 用户所做的那样。这不是纯粹的解决方案,但它避免了历史重写的中断,所以如果它满足您的需求,它可能是更好的实践中的解决方案。)

如果出于某种原因您确实需要更改存储在历史记录中的行结尾,那么您必须重写历史记录。也就是说,您必须将当前具有 CRLF 行结尾的所有提交替换为已替换行结尾的提交。

这意味着所有提交 ID(哈希)值都会发生变化,因此,如果您将这些值用于任何内容(例如发布文档或其他内容),则它要么需要更新,要么就会过时。这还意味着存储库的任何其他克隆(在构建服务器上或由其他开发人员使用)都需要更新。基本问题(以及重写分支历史记录时解决该问题的方法)可以在“从上游 rebase 恢复”下的 git rebase 文档中找到,但是对于全面的历史记录重写,最好让每个人都参与将所有更改推送到中央存储库,然后丢弃所有克隆,然后重写中央存储库的历史记录,然后让每个人重新克隆。如果这在您的情况下不切实际,那么我强烈建议不要尝试重写,因为如果有人在重写后尝试恢复时做错了事情,则重写可能会被撤消。

话虽如此,如果您决定这样做,该怎么做?

如果历史记录很小且简单,您可以使用rebase。例如,给定一个小的线性历史记录,您可以说 git rebase -i,将所有提交的命令更改为 edit,并查找并修复所有文件中的行结尾对于每个提交。不过,这很快就会变得乏味,如果您有任何“真实”的历史记录,您将需要更自动化的东西。

在最常见的情况下,您可以使用git filter-branch。最简单的方法是使用树过滤器;您将编写一个脚本来重写工作树中的所有行结尾(在本例中,我们将调用 filter.sh,然后给出类似的命令

git filter-branch --tree-filter filter.sh -- --all

如果存储库很大(大量提交和/或非常大的工作树),那么该命令将花费很长时间。您可以通过为 filter-branch 提供一个 ramdisk 来放置其工作树来加快速度,但这仍然是一个资源密集型操作。

使用索引过滤器会更快(但仍然可能不是“快”)。不过,它更复杂。可能您会预处理每个 BLOB(文件对象)历史记录,生成一个替换了行结尾的版本;然后您的脚本将运行命令来更新索引,通过将每个“旧”BLOB 替换为相应的新 BLOB。

我意识到最后一段涉及了一些并非每个人都知道的术语和概念,这就是重点。如果您了解得足够多,或者值得学习足够多的知识来理解和组装这样的过程,那么这是一个选择,并且它比使用树过滤器更快。

关于git - 在所有提交中将 CRLF 替换为 LF,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/54422721/

相关文章:

git 对存储库文件或路径的访问权限

git - 审阅者可以将他们的签名添加到特定的 git 提交吗?

git - git mergeworkingbranch后,如何消除错误 "error: cannot run sublime: No such file or directory"

git 相当于 'hg serve' ?

git - 当我从我的远程存储库中 pull 时,为什么 Git 会返回这些字符?

git - 如何让Git使用cntlm

git:如何查看分支中所做的更改

git - 让 'git diff' 忽略 ^M

Git clean 里面被忽略的文件夹

xcode - 无法从 xcode 中的提交中排除用户界面状态