重写 git 历史以将所有 CRLF 替换为 LF?

Xiè*_*léi 34 git

我打算将一个私有 Git 存储库从 win32 box 转移到 Ubuntu。虽然我可以做一个最终的 dos2unix 提交,但我想重写整个历史,所以一些 Git GUI 将正确显示日志/差异。例如,gitg将为每个 CR/LF 插入空行。

Mat*_*Mat 29

您可以使用git filter-branch--tree-filter选项,并指定--all分支。

这是一个示例(从一个带有 Unix 类型文本文件的空目录开始:

准备:

$ hexdump -C testfile 
00000000  61 0d 0a 62 0d 0a 63 0d  0a                       |a..b..c..|
00000009

$ git init
Initialized empty Git repository in /home/seigneur/tmp/a/.git/

$ git add testfile && git commit -m "dos file checked in"
[master (root-commit) df4970f] dos file checked in
 1 files changed, 3 insertions(+), 0 deletions(-)
 create mode 100644 testfile
Run Code Online (Sandbox Code Playgroud)

命令:

$ git filter-branch --tree-filter 'git ls-files -z | xargs -0 dos2unix' -- --all
Run Code Online (Sandbox Code Playgroud)

输出:

Rewrite df4970f63e3196216d5986463f239e51eebb4014 (1/1)dos2unix: converting file testfile to Unix format ...

Ref 'refs/heads/master' was rewritten

$ hexdump -C testfile 
00000000  61 0a 62 0a 63 0a                                 |a.b.c.|
00000006
Run Code Online (Sandbox Code Playgroud)

强烈建议事先做一个完整的备份。在你的 Linux 机器上运行它(除非你在 Windows 环境中设置了一个好的 shell)可能更容易。

编辑:转换第一次反转。


小智 6

Mat 的回答将这个问题牢牢地钉在了头上。不幸的是,在 Ubuntu Linux 上,从版本 10.04 (Lucid Lynx) 开始,dos2unix/unix2dos 命令不再可用,并已被 fromdos/todos 取代。此外,这两组转换命令对二进制文件的存在有不同程度的无知,因此如果您的存储库包含图像、字体等,它们将被此过程破坏。

我能够找到解决二进制文件损坏问题的方法,该问题使用 Linux 'file' 命令正确识别和处理仅文本文件,如下所示。下面的命令使用 --tag-name-filter 选项通过将现有标签移动到新修改的提交来保留现有标签。它还使用 --force 标志来确保该命令在您之前在存储库上运行过树过滤器的情况下可以工作。

git filter-branch --force --tree-filter 'git ls-files | xargs file | sed -n -e "/.*: .*text.*/s/\(.*\): .*/\1/p" | xargs fromdos' --tag-name-filter cat -- --all
Run Code Online (Sandbox Code Playgroud)