Git diff 显示的是用尖括号括起来的 Unicode 符号。

24

我有一个包含Unicode符号(俄语文本)的文件。 当我更正拼写错误时,我使用git diff --color-words=.命令查看所做的更改。

对于Unicode(西里尔字母)符号,我会遇到一些带有尖括号的混乱情况,如下所示:

$ cat p1
привет

$ cat p2
Привет

$ git diff --color-words=. --no-index p1 p2
diff --git 1/p1 2/p2
index d0f56e1..d84c480 100644
--- 1/p1
+++ 2/p2
@@ -1 +1 @@
<D0><BF><9F>ривет

看起来 git diff --color-words=. 检查的是字节之间的差异,而不是我期望的符号之间的差异。

有没有办法告诉 git 正确处理 Unicode 符号?

更新 关于我的环境:我在 Mac OS 和 Linux 主机上得到相同的结果。

我的 shell 变量是:

BASH=/bin/bash
HOSTTYPE=x86_64
LANG=ru_RU.UTF-8
OSTYPE=darwin10.0
PS1='\h:\W \u\$ '
SHELL=/bin/bash
SHELLOPTS=braceexpand:emacs:hashall:histexpand:history:interactive-comments:monitor
TERM=xterm-256color
TERM_PROGRAM=iTerm.app
_=-l

我已将Git配置重置为默认设置,方法如下:

$ git config -l
core.repositoryformatversion=0
core.filemode=true
core.bare=false
core.logallrefupdates=true
core.ignorecase=true

Git 版本

$ git --version
git version 1.7.3.5

3
这不是 git diff 显示 "<>",而是默认分页程序 less 显示的。尝试导出 LESSOPTS=-RLESSOPTS=-RX 看看是否有帮助。此外,你的问题存在一个问题:你没有提供任何关于你的环境信息。 - kostix
我已经更新了我的环境细节。我也尝试配置git pager,像这样:$ git config --global core.pager "less -R",但这并没有帮助。 - chestozo
我也尝试过这个:$ GIT_PAGER='' git diff --no-index --color-words=. p1 p2 你好$ GIT_PAGER='' git diff --no-index --color-words=. --no-color p1 p2 你好 - chestozo
1
"--word-diff-regex=." 在字节级别上工作并破坏多字节字符。不幸的是,此选项也不支持代码点范围(尝试了 posix 和 pcre 符号但都没有起作用)。 - Jokester
6个回答

38

对我来说,less——git分页器——有问题(感谢@kostix)。尝试禁用分页器:

git --no-pager diff p1 p2

我的情况是包含表情符号的提交消息;尽管如此,根本问题是相同的。

$ git log --oneline
93a1866 <U+1F43C>

$ git --no-pager log --oneline
93a1866 

$ export LESS='--raw-control-chars'
$ git log --oneline
93a1866 

$ git config --global core.pager 'less --raw-control-chars'
$ git log --oneline
93a1866 

NB:使用--RAW-CONTROL-CHARS选项会使less传递ANSI颜色转义序列,但仍会破坏其他控制字符(包括表情符号)。我的less全局配置了--RAW-CONTROL-CHARS,并且我的git分页器也是如上配置的--raw-control-chars


1
重要的部分是 --color-words=.,因为我想看到符号差异。运行 git --no-pager show --color-words=. 后,我得到了这个:���ривет。对于 git --no-pager diff --color-words=. --no-index p1 p2 也是一样。 - chestozo
3
git config --global core.pager 'less --raw-control-chars'正是我需要的,以解决git-log的显示问题。 - simey.me
对我没有用,有其他建议吗?我已经在*~/.gitconfig中的[core]下添加了pager = less -FrSX,但没有帮助。我的环境变量LANG*是en_US.UTF-8;env LESS-M -I -R(尝试将-R更改为-r不会改变行为)。 - Kamafeather

21

对我而言,最好的解决方案是设置 export LESSCHARSET=utf-8

这样做后,git log -pgit diff 命令都可以正常显示 Unicode 字符。


对我来说不起作用。我在.gitconfig中有pager = less -rFX,这就是我得到的结果 https://d17oy1vhnax1f7.cloudfront.net/items/2p3703271r0m060s1J34/s.png?v=2d60f213 - chestozo
你的LANG设置了吗? 我的是LANG=en_US.UTF-8 - Magomed Abdurakhmanov
这是我使用 git diffgit diff --color-words=. 得到的结果。https://www.dropbox.com/s/2wt9iysevw2xeyn/Screenshot%202016-12-25%2023.09.02.png?dl=0 - Magomed Abdurakhmanov
当你改变了西里尔字时,这就是它的样子。 - Magomed Abdurakhmanov
1
这对我有用。创建了一个新的环境变量LESSCHARSET,设置为utf-8,现在git log/diff正确显示挪威字母ÆØÅ,而不是显示为<C3><85>等字符。操作系统:Windows 10。 - ardal
显示剩余2条评论

3
我的解决方案是使用git difftool。 我基于google-diff-match-patch编写了这个工具https://github.com/chestozo/dmp。 有时候它也比git diff --color-words=更好地显示差异。 :)

3

对于一些平台,将LANG设置为C.UTF-8(或en_US.UTF-8等)就可以解决问题:

$ echo '人' >test1.txt && echo '丁' >test2.txt
$ LANG=C.UTF-8 git diff --no-index --word-diff=plain --word-diff-regex=. -- test1.txt test2.txt
diff --git a/test1.txt b/test2.txt
index 3ef0891..3773917 100644
--- a/test1.txt
+++ b/test2.txt
@@ -1 +1 @@
[-人-]{+丁+}

然而,在某些平台上(例如Git for Windows),LANG似乎没有被采纳:

$ echo '人' >test1.txt && echo '丁' >test2.txt
$ LANG=C.UTF-8 git diff --no-index --word-diff=plain --word-diff-regex=. -- test1.txt test2.txt
diff --git a/test1.txt b/test2.txt
index 3ef0891..3773917 100644
--- a/test1.txt
+++ b/test2.txt
@@ -1 +1 @@
<E4>[-<BA><BA>-]{+<B8><81>+}

在这些平台上的解决方法是提供UTF-8字符的原始字节(例如,对于'.',使用$'[^\x80-\xBF][\x80-\xBF]*'),然后在git diff中使用:
$ echo '人' >test1.txt && echo '丁' >test2.txt
$ git diff --no-index --word-diff=plain --word-diff-regex=$'[^\x80-\xBF][\x80-\xBF]*' -- test1.txt test2.txt
diff --git a/test1.txt b/test2.txt
index 3ef0891..3773917 100644
--- a/test1.txt
+++ b/test2.txt
@@ -1 +1 @@
[-人-]{+丁+}

我的情况中LANG变量是en_US.UTF-8,但它并没有什么帮助。git diff --color-words=. --word-diff-regex=$'[^\x80-\xBF][\x80-\xBF]*' 是个好方法!谢谢 :) 我会试一下的! - chestozo
1
如果您正在使用--word-diff-regex,最好使用--word-diff=color而不是--color-words(这是两者的组合)。此外,您可以设置diff.wordRegex,以便将来只需提供--word-diff=color,git 将使用配置的正则表达式进行单词差异。 - Danny Lin
在git diffs中渲染UTF8字符时要小心,可以通过使用可疑的UTF8字符(我指的是零宽字符)来隐藏一些恶意代码。 - Yarek T

1

toolbear的答案对我没有用,因为即使使用git --no-pager diff,我仍然看到了不可读的字符(不是括号,而是不可读的),所以less不是核心问题。

我尝试了很多方法,但唯一有用的方法是将明确的 Cyrillic 到 utf-8 转换包含在 .git\config 中(我正在使用 windows 7)。

[pager]
diff = iconv.exe -f cp1251 -t utf-8 | less  

注意,我在这里特别更改了 pager.diff,因为我只有在使用 diff 命令时才遇到编码问题。出于某种奇怪的原因,logreflog 对我来说运行良好。但如果您在使用其他命令时也遇到编码问题,则应将 pager 更改为所有命令,如下所示:
[core]
...
pager = iconv.exe -f cp1251 -t utf-8 | less 

0

我看到很多报告说xterm在某些情况下无法正确打印Unicode字符。也许这可以作为解决方案的起点。


1
在这种情况下,问题出在用于在 shell 中表示 Unicode 符号的 2 个字节上。 而 git diff 只知道如何处理 1 个字节的符号。 我不确定这是否是 xterm 的问题。 - chestozo
嗯...看起来好像不行...至少对我来说是这样的 diff --git a/README b/README index e69de29..b562a56 100644 --- a/README +++ b/README @@ -0,0 +1 @@ +µÜäčřúůжжвыаьь - frlan

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接