我正在跟踪git中的虚拟PC虚拟机文件(* .vmc),并且在进行更改后,git将该文件识别为二进制文件并且不会为我进行区分。我发现文件是用UTF-16编码的。
可以教git识别这个文件是文本并妥善处理吗?
我在Cygwin下使用git,core.autocrlf设置为false。如果需要,我可以在UNIX下使用mSysGit或git。
答案 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
文件:
使用以下命令在存储库的根目录中创建.gitattributes
文件:
*.strings diff=localizablestrings
将以下内容添加到~/.gitconfig
文件中:
[diff "localizablestrings"]
textconv = "iconv -f utf-16 -t utf-8"
来源:Diff .strings files in Git(以及2010年的older post)。
答案 2 :(得分:36)
您是否尝试过设置.gitattributes
将其视为文本文件?
e.g:
*.vmc diff
答案 3 :(得分:28)
默认情况下,git
看起来不适用于UTF-16;对于这样的文件,您必须确保没有对其进行CRLF
处理,但您希望diff
和merge
作为普通文本文件工作(这忽略了是否您的终端/编辑器可以处理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假定反斜杠目录分隔符。
创建将转换为stdout的单个参数脚本。 C:\路径\到\一些\ script.sh:
[diff "jpg"]
textconv = exif
设置git以便能够使用脚本文件。在您的git配置(#!/bin/bash
SED='s/\//\\\\\\\\/g'
FILE=\`echo $1 | sed -e "$SED"\`
cmd.exe /c "type $FILE"
或~/.gitconfig
或查看.git/config
)中,请输入:
man git-config
使用.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-utf8(to-utf8
脚本位于同一个仓库中。)
请注意,此脚本需要在系统上提供file
和iconv
命令。
答案 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一起提供的dos2unix
和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...
答案 8 :(得分:1)
如其他答案中所述,git diff 不会将 UTF-16 文件作为文本处理,例如,这使得它们在 Atlassian SourceTree 中无法查看。如果文件名/或后缀已知,下面的修复将使这些文件在 SourceTree 下正常可见和可比。
如果 UTF-16 文件的文件后缀是已知的(例如 *.uni),那么所有具有该后缀的文件都可以与 UTF-16 到 UTF-8 转换器相关联,并进行以下两项更改:
使用以下行在存储库的根目录中创建或修改 .gitattributes 文件:
*.uni diff=utf16
然后使用以下部分修改用户主目录(C:\Users\yourusername\.gitconfig)中的 .gitconfig 文件:
[diff=utf16]
textconv = "iconv -f utf-16 -t utf-8"
这两项更改应立即生效,无需将存储库重新加载到 SourceTree 中。它将文本转换应用于所有 *.uni 文件,这使得它们像其他文本文件一样可见和比较。如果其他文件需要此转换,您可以在 .gitattributes 文件中添加额外的行。 (如果指定的文件不是 UTF-16,您将获得无法读取该文件的结果。)
请注意,此答案是对 Tony Kuneck 答案的简化重写。