我要将一个私有 Git 存储库从 win32 机器转移到 Ubuntu。虽然我可以进行最终的 dos2unix 提交,但我想重写整个历史记录,以便某些 Git GUI 可以正确显示日志/差异。例如,吉特格将为每个 CR/LF 插入空行。
答案1
您可以使用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
命令:
$ git filter-branch --tree-filter 'git ls-files -z | xargs -0 dos2unix' -- --all
输出:
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
我强烈建议事先进行完整备份。从您的 Linux 机器运行该程序(除非您在 Windows 环境中设置了良好的 shell)可能更容易。
编辑:第一次转换时被逆转了。
答案2
Mat's回答一针见血地指出了这个问题。不幸的是,在 Ubuntu Linux 上,从版本 10.04(Lucid Lynx)开始,dos2unix/unix2dos 命令不再可用,已被 fromdos/todos 取代。此外,这两组转换命令对二进制文件的存在都有不同程度的忽略,因此如果您的存储库包含图像、字体等,它们将被此过程破坏。
我找到了一种解决二进制文件损坏问题的方法,即使用 Linux 的“file”命令正确识别和处理文本文件,如下所示。下面的命令使用 --tag-name-filter 选项,通过将现有标签移动到新修改的提交来保留它们。此外,它还使用 --force 标志来确保如果您之前在存储库上运行过 tree-filter,该命令仍能正常工作。
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
答案3
并且无需任何附加工具(例如“fromdos”、“dos2unix”等):
git filter-branch --force --tree-filter 'git ls-files | xargs file | sed -n -e "/.*: .*text.*/s/\(.*\): .*/\1/p" | xargs -0 sed -i"" -e "s/"$(printf "\015")"$//"' --tag-name-filter cat -- --all
跨平台(OS X、FreeBSD、Linux)有用的模拟‘fromdos’、‘dos2unix’:
sed -i'' -e 's/'"$(printf '\015')"'$//'
也许有用的‘unix2dos’:
sed -i '' -e 's|$|'"`printf '\015'`"'|' file.name
如果你非常清楚自己在做什么,你可以使用这个简单的内联命令从当前目录“。”中的所有文件中删除“/r”:
find . -type f -exec sed -i'' -e 's/'"$(printf '\015')"'$//' {} \;
答案4
git filter-branch
有几个问题,主要是在性能方面,因为已被弃用git filter-repo
,一个由几个python脚本组成的单独项目。
要转换存储库中的所有行尾,请使用lint-history
lint-history dos2unix # CRLF => LF
lint-history unix2dos # LF => CRLF
您还可以执行其他 linting 任务,例如在文件末尾添加换行符
lint-history sed -i '$a\'
这假定lint-history
脚本在您的路径中,并且已git filter-repo
使用符号链接等正确安装。
如果您没有完整filter-repo
安装lint-history
但只有git-filter-repo
您可以运行:
git filter-repo --blob-callback '
if not b"\0" in blob.data[0:8192]:
filename = ".git/info/tmpfile"
with open(filename, "wb") as f:
f.write(blob.data)
subprocess.check_call(["sed", "-i", "$a\\", filename])
with open(filename, "rb") as f:
blob.data = f.read()
os.remove(filename)
'