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

问题描述 投票:126回答:8

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

可以教git识别这个文件是文本并适当处理它吗?

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

git unicode character-encoding diff utf-16
8个回答
77
投票

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

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

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

找到“difftool”太长,无法输入?没问题:

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

Git岩石。


60
投票

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

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

  1. 使用以下命令在存储库的根目录中创建.gitattributes文件: *.strings diff=localizablestrings
  2. 将以下内容添加到~/.gitconfig文件中: [diff "localizablestrings"] textconv = "iconv -f utf-16 -t utf-8"

资料来源:Diff .strings files in Git(以及2010年的older post)。


37
投票

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

e.g:

*.vmc diff

更多细节在http://www.git-scm.com/docs/gitattributes.html


30
投票

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

但是看看.gitattributes manpage,这里是binary的自定义属性:

[attr]binary -diff -crlf

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

[attr]utf16 diff merge -crlf

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

*.vmc utf16

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

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 diff似乎不是unicode。

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


8
投票

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

从gitattributes手册页引用:


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

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

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

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

[diff "jpg"]
        textconv = exif

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

步骤1:

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

#!/bin/bash
SED='s/\//\\\\\\\\/g'
FILE=\`echo $1 | sed -e "$SED"\`
cmd.exe /c "type $FILE"

第2步:

设置git以便能够使用脚本文件。在你的git配置(~/.gitconfig.git/config或参见man git-config)中,把这个:

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

第3步:

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

*vmc diff=cmdtype

然后在你的文件上使用git diff


4
投票

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

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


3
投票

git最近开始理解utf16这样的编码。请参阅gitattributes docs,搜索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

(将*.vmc替换为需要处理的*.whatever类型文件的whatever

见:Support working-tree-encoding "UTF-16LE-BOM"


1
投票

最近在Windows上出现了这个问题,并且使用git for windows附带的dos2unixand unix2dos垃圾箱就可以了。默认情况下,它们位于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...
© www.soinside.com 2019 - 2024. All rights reserved.