我可以让git将UTF-16文件识别为文本吗?

时间:2009-04-22 15:51:32

标签: git unicode character-encoding diff utf-16

我正在跟踪git中的虚拟PC虚拟机文件(* .vmc),并且在进行更改后,git将该文件识别为二进制文件并且不会为我进行区分。我发现文件是用UTF-16编码的。

可以教git识别这个文件是文本并妥善处理吗?

我在Cygwin下使用git,core.autocrlf设置为false。如果需要,我可以在UNIX下使用mSysGit或git。

9 个答案:

答案 0 :(得分:75)

我一直在努力解决这个问题,并且刚刚发现(对我来说)一个完美的解决方案:

$ git config --global diff.tool vimdiff      # or merge.tool to get merging too!
$ git difftool commit1 commit2

git difftool采用与git diff相同的参数,但运行您选择的diff程序而不是内置的GNU diff。因此,选择一个支持多字节的差异(在我的情况下,在差异模式下为vim)并使用git difftool代替git diff

查找“difftool”太长而无法输入?没问题:

$ git config --global alias.dt difftool
$ git dt commit1 commit2

Git rocks。

答案 1 :(得分:58)

有一个非常简单的解决方案可以在Unices上开箱即用。

例如,使用Apple的.strings文件:

  1. 使用以下命令在存储库的根目录中创建.gitattributes文件:

    *.strings diff=localizablestrings
    
  2. 将以下内容添加到~/.gitconfig文件中:

    [diff "localizablestrings"]
    textconv = "iconv -f utf-16 -t utf-8"
    
  3. 来源:Diff .strings files in Git(以及2010年的older post)。

答案 2 :(得分:36)

您是否尝试过设置.gitattributes将其视为文本文件?

e.g:

*.vmc diff

http://www.git-scm.com/docs/gitattributes.html的更多详情。

答案 3 :(得分:28)

默认情况下,git看起来不适用于UTF-16;对于这样的文件,您必须确保没有对其进行CRLF处理,但您希望diffmerge作为普通文本文件工作(这忽略了是否您的终端/编辑器可以处理UTF-16。

但是查看.gitattributes manpage,这是自定义属性binary

[attr]binary -diff -crlf

因此,在我看来,您可以在.gitattributes的顶级utf16中定义自定义属性(请注意,我在此添加合并以确保将其视为文本):

[attr]utf16 diff merge -crlf

从那里,您可以在任何.gitattributes文件中指定类似:

*.vmc utf16

另请注意,即使git认为文件是二进制文件,您仍然可以diff一个文件:

git diff --text

修改

This answer基本上说GNU diff与UTF-16甚至UTF-8都不能很好地工作。如果您希望git使用其他工具来查看差异(通过--ext-diff),则该答案会显示Guiffy

但您可能需要的只是diff只包含ASCII字符的UTF-16文件。一种方法是使用--ext-diff和以下shell脚本:

#!/bin/bash
diff <(iconv -f utf-16 -t utf-8 "$1") <(iconv -f utf-16 -t utf-8 "$2")

请注意,转换为UTF-8也可能适用于合并,您只需要确保它在两个方向都完成。

在查看UTF-16文件的差异时输出到终端:

  

试图像这样的差异导致   二进制垃圾喷到了屏幕上。   如果git使用GNU diff,那就可以了   似乎GNU差异不是   Unicode感知的。

GNU diff并不真正关心unicode,所以当你使用diff --text时它只是差异并输出文本。问题是您使用的终端无法处理发出的UTF-16(与ASCII字符的差异标记结合)。

答案 4 :(得分:8)

解决方案是过滤cmd.exe /c "type %1"。 cmd的type内置将进行转换,因此你可以使用git diff的textconv能力来启用UTF-16文件的文本差异(也应该使用UTF-8,虽然未经测试)。

从gitattributes手册页引用:


执行二进制文件的文本差异

有时需要查看某些二进制文件的文本转换版本的差异。例如,可以将文字处理器文档转换为ASCII文本表示,并显示文本的差异。即使这种转换失去了一些信息,生成的差异对人类观看也很有用(但不能直接应用)。

textconv配置选项用于定义执行此类转换的程序。该程序应该采用一个参数,即要转换的文件的名称,并在stdout上生成结果文本。

例如,要显示文件的exif信息的差异而不是二进制信息(假设您已安装exif工具),请将以下部分添加到$GIT_DIR/config文件(或{{1}文件):

$HOME/.gitconfig

mingw32 的解决方案,cygwin粉丝可能不得不改变方法。问题是传递文件名以转换为cmd.exe - 它将使用正斜杠,cmd假定反斜杠目录分隔符。

第1步:

创建将转换为stdout的单个参数脚本。 C:\路径\到\一些\ script.sh:

[diff "jpg"]
        textconv = exif

第2步:

设置git以便能够使用脚本文件。在您的git配置(#!/bin/bash SED='s/\//\\\\\\\\/g' FILE=\`echo $1 | sed -e "$SED"\` cmd.exe /c "type $FILE" ~/.gitconfig或查看.git/config)中,请输入:

man git-config

第3步:

使用.gitattributes文件指出要应用此工作区的文件(参见man gitattributes(5)):

[diff "cmdtype"]
textconv = c:/path/to/some/script.sh

然后在您的文件上使用*vmc diff=cmdtype

答案 5 :(得分:4)

我编写了一个小的git-diff驱动程序to-utf8,它可以很容易地区分任何非ASCII / UTF-8编码的文件。您可以使用以下说明进行安装:https://github.com/chaitanyagupta/gitutils#to-utf8to-utf8脚本位于同一个仓库中。)

请注意,此脚本需要在系统上提供fileiconv命令。

答案 6 :(得分:2)

git最近已经开始了解utf16等编码。 查看gitattributes文档,搜索working-tree-encoding

[请确保您的手册页匹配,因为这是很新的!]

如果(说)该文件是Windows计算机上没有bom的utf-16,则将其添加到您的gitattributes文件中

*.vmc text working-tree-encoding=UTF-16LE eol=CRLF

如果* nix上的utf-16(带有bom)成功

*.vmc text working-tree-encoding=UTF-16 eol=LF

答案 7 :(得分:1)

最近在Windows上出现了此问题,而git随Windows一起提供的dos2unixunix2dos垃圾箱解决了这个问题。默认情况下,它们位于C:\Program Files\Git\usr\bin\中。 只有在您的文件不需要需要为UTF-16时,才可以观察到这一点。例如,某人意外地将一个python文件编码为UTF-16。需要(以我为例)。

PS C:\Users\xxx> dos2unix my_file.py
dos2unix: converting UTF-16LE file my_file.py to ANSI_X3.4-1968 Unix format...

PS C:\Users\xxx> unix2dos my_file.py
unix2dos: converting UTF-16LE file my_file.py to ANSI_X3.4-1968 DOS format...

答案 8 :(得分:1)

如其他答案中所述,git diff 不会将 UTF-16 文件作为文本处理,例如,这使得它们在 Atlassian SourceTree 中无法查看。如果文件名/或后缀已知,下面的修复将使这些文件在 SourceTree 下正常可见和可比。

如果 UTF-16 文件的文件后缀是已知的(例如 *.uni),那么所有具有该后缀的文件都可以与 UTF-16 到 UTF-8 转换器相关联,并进行以下两项更改:

  1. 使用以下行在存储库的根目录中创建或修改 .gitattributes 文件:

     *.uni diff=utf16
    
  2. 然后使用以下部分修改用户主目录(C:\Users\yourusername\.gitconfig)中的 .gitconfig 文件:

    [diff=utf16]
        textconv = "iconv -f utf-16 -t utf-8"
    

这两项更改应立即生效,无需将存储库重新加载到 SourceTree 中。它将文本转换应用于所有 *.uni 文件,这使得它们像其他文本文件一样可见和比较。如果其他文件需要此转换,您可以在 .gitattributes 文件中添加额外的行。 (如果指定的文件不是 UTF-16,您将获得无法读取该文件的结果。)

请注意,此答案是对 Tony Kuneck 答案的简化重写。