![](/img/trans.png)
[英]Convert file to iso-8859-1 (ok from utf-8 but fails on us-ascii files)
[英]Switching a Git repository from ISO-8859-1 to UTF-8 encoding for source code files
我将在本周末使用快速导出将大型Mercurial项目转换为Git。 我已经多次测试了,结果很好。
我们还希望将我们的源代码编码(许多德语注释/字符串文字与Umlauts)从ISO-8859-1转换为UTF-8(repo中的所有其他非java文件应保持原样),并且Git迁移为我们提供了一个机会,因为每个人都需要再次克隆。 但是,我找不到一个好的方法。
git filter-tree --tree-filter ...
方法来评论SO 。 然而,虽然这似乎是理想的,但由于存储库的大小(大约200000次提交,18000个代码文件),它将花费比我周末更多的时间。 我已经尝试运行它(在一个高度优化的版本中,文件列表被分块并且子列表并行转换(使用GNU并行 ))直接来自具有72个内核的Linux VM上的64GB tmpfs卷,但它仍然会需要几天...... --all
为<rev-list>
),但都只是一些过去的承诺是承诺从目前活跃的分支到达和不可到达(希望)所有当前分支的前身( branch-a branch-b branch-c --not old-tag-before-branch-abc-forked-off
as <rev-list>
)。 它仍在运行,但我担心我不能真正相信结果,因为这似乎是一个非常糟糕的主意。 所以现在,我觉得最好的解决办法就是坚持使用ISO-8859-1。
有没有人有想法? 有人提到, reposurgeon可能基本上接近1使用其transcode
操作,其性能比git filter-tree --tree-filter ...
但我不知道它是如何工作的。
git filter-branch
树过滤git filter-branch
本质上很慢。 它的工作原理是将每个提交提取到一个临时目录中的完整树中,让您更改每个文件,然后找出您更改的内容并从您留下的每个文件中进行新提交。
如果您通过快速导出/快速导入导出和导入, 那么就是转换数据的时间:在将文件写入内容之前,您在文件系统中将扩展的文件数据放在内存中,而不是文件系统形式。出口/进口管道。 而且, git fast-import
本身就是一个shell脚本,因此在那里插入过滤是微不足道的,而hg-fast-export
是一个Python程序,因此在那里插入过滤也很简单。 显而易见的地方就在这里 :只需重新编码d
。
您可以考虑使用git filter-branch --index-filter
-as,而不是--tree-filter
(这是默认值)。 这个想法是使用--index-filter
,没有结帐步骤(即每次迭代都没有(重新)填充工作树)。
所以你可以考虑为git filter-branch --index-filter
编写一个过滤git filter-branch --index-filter
,它将使用git ls-files
东西:
调用git ls-files --cached --stage
并遍历每个条目。
仅考虑那些具有100644
文件模式的文件 - 即普通文件。
对于每个条目运行的东西
sha1=`git show ":0:$filename" \\ | iconv -f iso8859-1 -t utf-8 \\ | git hash-object -t blob -w --stdin` git update-index --cacheinfo "10644,$sha1,$filename" --info-only
冲洗,重复。
我想要的另一种方法是从不同的角度解决问题:由git fast-export
生成并由git fast-import
消耗的流的格式是纯文本¹(只需将导出器的输出传输给less
或另一个寻呼机并查看你自己)。
您可以使用您喜欢的PL编写一个过滤器来解析流,重新编码任何data
块。 流的组织方式使得不使用SHA-1哈希,因此您可以随时重新编码。 我唯一明显的问题是data
块没有关于它们将在结果提交中表示哪个文件的信息(如果有的话),所以如果你的历史记录中有非文本文件,你可能需要采用基于猜测的方法。关于每个数据blob的内容,或者通过记住它看到的blob并决定在看到将文件名分配给(某些)blob的commit
记录后重新编码它们中的哪一个来使处理器更复杂。
¹用git-fast-import(1)
-run git help fast-import
。
我有完全相同的问题,解决方案基于@kostix回答使用filter-branch
的--index-filter
选项作为基础,但是,有一些额外的改进。
git diff --name-only --staged
来检测暂存区域的内容 git ls-files $filename
,即它不是已删除的文件 git show ":0:$filename" | file - --brief --mime-encoding
的结果git show ":0:$filename" | file - --brief --mime-encoding
git show ":0:$filename" | file - --brief --mime-encoding
不是binary
,即它是一个文本文件,也不是UTF-8编码的 git ls-files $filename --stage | cut -c 1-6
检测文件模式 git ls-files $filename --stage | cut -c 1-6
这是我的bash函数的外观:
changeencoding() {
for filename in `git diff --name-only --staged`; do
# Only if file is present, i.e., filter deletions
if [ `git ls-files $filename` ]; then
local encoding=`git show ":0:$filename" | file - --brief --mime-encoding`
if [ "$encoding" != "binary" -a "$encoding" != "utf-8" ]; then
local sha1=`git show ":0:$filename" \
| iconv --from-code=$encoding --to-code=utf-8 \
| git hash-object -t blob -w --stdin`
local mode=`git ls-files $filename --stage | cut -c 1-6`
git update-index --cacheinfo "$mode,$sha1,$filename" --info-only
fi
fi
done
}
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.