现有的Git存储库,带有混合编码的文件

问题描述 投票:1回答:1

我有一个现有的存储库,其中包含混合编码的文件-有些文件使用UTF-8,有些使用ANSI(例如Windows-1252)。大部分情况下一切正常,除了在ANSI文件上执行差异时我已经厌倦了看到“无效字符”,而且令我特别恼火的是,我无法使用我的GUI工具来对这些字符进行暂存或取消暂存。我正在寻找一种说服Git的方法,即某个文件使用非UTF-8编码,以便Git首先执行转换,然后对此进行魔术处理。

据我所知,有两种实现结果的方法:

自定义二进制文本过滤器

  1. 向我的.gitconfig添加转换过滤器:
    [diff "win1252"]
    textconv = "iconv -f windows-1252 -t utf-8"
  1. .gitattributes中,将文件标记为二进制文件并请求使用此过滤器将其转换为文本:
    *.txt    diff=win1252

此方法似乎在孤立的git diff中可以很好地工作,但是我遇到了几个我不知道如何解决的问题:

  1. 即使使用core.autocrlf = true,该方法也不会在转换命令的输出上执行CRLF转换,因此我的差异将显示更改后的行的行尾差异。我可以创建一个脚本,该脚本将运行iconv来执行编码转换,然后将输出传递给dos2unix来执行EOL转换,但是似乎比较笨拙。
  2. 由于外部工具的使用非常频繁,因此我的运行速度明显下降。
  3. 看来,命令行和我的GUI(SourceTree)在暂存时都不遵循转换设置。 git add -p显示垃圾(甚至比“未知字符”还要糟糕),并且SourceTree停止分段并显示一条错误消息,即找不到原始文本。

虽然我可能能够学习与#1和#2一起生活,但#3是一个阻塞问题,因为我主要需要进行此转换以促进带有“未知字符”的帅哥的演出。我当前的工作流程使用git add -p而不进行任何转换,可能会显示“未知字符”,但至少可以正常工作。

GUI的更改不切实际:我尝试过的所有其他GUI都比这严重得多。

使用工作树编码属性

  1. .gitattributes中,将文件标记为具有自定义编码的文本文件:
    *.txt    text working-tree-encoding=windows-1252

据我所知,这种方法涵盖了上面列出的所有抱怨,并且在命令行和GUI中都可以正常工作。不幸的是,有一个主要警告:它仅适用于在设置了该属性后created的文件。对于在添加此属性之前创建的文件,Git将为每个包含这些未编码字符的文件显示更改(从“未知字符”到Windows-1252)。另外,克隆存储库后,它会抱怨它“未能将'a.txt'从UTF-8编码到Windows-1252”。看来文件实际上是正确克隆的(与原始字节逐字节匹配),但仍然显示出差异。基本上,我将不得不使用“未知字符”提交每个文件,以将其重新编码为存储库中的UTF-8,这将使我的历史陷入困境,并使Blame无法使用。

似乎可行的方法可能是使用类似git filter-branch的方法,但是对于整个存储库(是否有类似的方法?),将所有现有文件转换为UTF-8 并且将属性添加到第一次提交,但我担心要做这么大的事情。另外,我希望我会丢失以前的提交ID,这是不幸的(我在可执行文件上标记了提交ID,以便轻松地定位其生成版本)。


是否有任何方法可以克服所描述方法的缺点,或者是否有另一种方法不易受其影响?

git encoding utf-8 repository ansi
1个回答
1
投票

通过使用working-tree-encoding,您处在正确的轨道上,但还需要再执行一步。

在创建.gitattributes文件的同一提交中,运行git add --renormalize .,它将获取所有工作树文件并根据指定的编码对其进行过滤。然后,您要在同一次提交中提交所有更改的文件和.gitattributes文件,然后将它们以UTF-8的形式存储在存储库中,但在您的工作树中为Windows-1252。

这确实有一个缺点,即git blame必须跳回该提交之外,但是您可以指定--ignore-rev--ignore-revs-file(或配置选项blame.ignoreRevsFile)忽略该修订,一切都会正常进行。

© www.soinside.com 2019 - 2024. All rights reserved.