MacOSX上的Git和Umlaut问题

MacOSX上的Git和Umlaut问题,git,macos,versioning,Git,Macos,Versioning,今天我在MacOSX上发现了Git的一个bug 例如,我将提交一个名为überschrift.txt的文件,文件开头带有德语特殊字符Ü。通过命令git status我得到以下输出 Users-iMac: user$ git status On branch master # Untracked files: # (use "git add <file>..." to include in what will be committed) # # "U\314\210bersc

今天我在MacOSX上发现了Git的一个bug

例如,我将提交一个名为überschrift.txt的文件,文件开头带有德语特殊字符Ü。通过命令
git status
我得到以下输出

Users-iMac: user$ git status

On branch master
# Untracked files:
#   (use "git add <file>..." to include in what will be committed)
#
#   "U\314\210berschrift.txt"
nothing added to commit but untracked files present (use "git add" to track)
Users-iMac:user$git-status
论分行行长
#未跟踪的文件:
#(使用“git add…”包含在将提交的内容中)
#
#“U\314\210berschrift.txt”
提交时未添加任何内容,但存在未跟踪的文件(使用“git add”跟踪)
Git1.7.2似乎在MacOSX上的德语特殊字符方面存在问题。 有没有办法让Git读取正确的文件名?

这是正确的

您的文件名在中,Ü表示为拉丁文大写字母U+结合分音符(Unicode 0x0308,utf8 0xcc 0x88),而不是拉丁文大写字母U加分音符(Unicode 0x00dc,utf8 0xc3 0x9c)。这个依次显示非ASCII文件名字节的八进制转义形式


请注意,Unicode文件名会使存储库不可移植。例如,.

原因是文件系统存储文件名的方式不同

在Unicode中,Ü可以用两种方式表示,一种是用Ü单独表示,另一种是用U+“组合umlaut字符”表示。Unicode字符串可以同时包含这两种形式,但由于两者都包含很容易混淆,文件系统通过将每个umlauted-U设置为Ü或U+“组合umlaut字符”来规范Unicode字符串

Linux使用前一种方法,称为标准形式组合(或NFC),MacOSX使用后一种方法,称为标准形式分解(NFD)

显然不关心这一点,只使用文件名的字节序列,这就导致了您遇到的问题


邮件列表线程中有一个补丁,以便Git在标准化后比较文件名。

要使Git add file在Mac OS X上使用文件名中的umlauts,您可以使用
iconv
将文件路径字符串从组合转换为规范分解的UTF-8

# test case

mkdir testproject
cd testproject

git --version    # git version 1.7.6.1
locale charmap   # UTF-8

git init
file=$'\303\234berschrift.txt'    # composed UTF-8 (Linux-compatible)
touch "$file"
echo 'Hello, world!' > "$file"

# convert composed into canonically decomposed UTF-8
# cf. http://codesnippets.joyent.com/posts/show/12251
# printf '%s' "$file" | iconv -f utf-8 -t utf-8-mac | LC_ALL=C vis -fotc 
#git add "$file"
git add "$(printf '%s' "$file" | iconv -f utf-8 -t utf-8-mac)"  

git commit -a -m 'This is my commit message!'
git show
git status
git ls-files '*'
git ls-files -z '*' | tr '\0' '\n'

touch $'caf\303\251 1' $'caf\303\251 2' $'caf\303\251 3'
git ls-files --other '*'
git ls-files -z --other '*' | tr '\0' '\n'

在mac上启用core.precomposeunicode

git config --global core.precomposeunicode true
要使其工作,您至少需要有Git 1.8.2

山狮号飞船搭载1.7.5。要获得更新的git,请使用或(需要Xcode)


就这样

将存储库的特定于OSX的
core.precomposeunicode
标志更改为true:

git config core.precomposeunicode.true
要确保新存储库获得该标志,请同时运行:

git config --global core.precomposeunicode true
以下是手册页中的相关片段:

此选项仅由Git的Mac OS实现使用。什么时候 core.precomposeunicode=true,Git还原 由Mac OS完成的文件名。这在共享存储库时非常有用 在Mac OS和Linux或Windows之间。(Git适用于Windows 1.7.10或更高版本 是必需的,或者是cygwin 1.7下的Git)。如果为false,则文件名为 Git完全透明处理,它向后兼容 Git的旧版本


我的个人存储库也有类似的问题,所以我用Python3编写了一个助手脚本。您可以在此处绘制它:


脚本需要一些手工劳动,但不需要太多。

以下输入~/.gitconfig在10.12.1 Sierra上适用于UTF-8名称:

precomposeunicode = true
quotepath = false

第一个选项需要git“理解”UTF-8,第二个选项需要git“理解”UTF-8,这样它就不会转义字符。

我尝试了这个选项,但没有成功。它仍然很混乱,无法找到文件。Umlaut规范化是一个巨大的错误。文件系统的构建方式不应该让运行在上面的东西不得不“关心”发生的奇怪修改。肯·汤普森会说这不是一种特征,而是一种症状。它几乎可以破坏任何系统——不仅仅是git。我最近复制了一个web转储。Umlaut规范化破坏了它,因为html文件引用了文件名中包含Umlaut的图像。我打赌这也是一个安全问题。实际上,Linux并不总是使用NFC。Linux(与内核和文件系统一样)并不关心文件名,而是将其视为字节数组。规范化取决于C库和应用程序;大多数人都使用NFC,但这只是一种惯例。奇怪的是,对我来说,情况正好相反(
git config--global core.precomposeunicode false
)。我正在运行OSX10.9.2和Git1.8.5.2,文件存储在带有HFS+文件系统的磁盘映像上。可能是苹果改变了他们的实现方式吗?Kudos@Philipp——这一改变成功了。这将是答案的重要更新!在OSX10.10和Git2.0.0上,我必须将配置参数设置为
false
。我不必再次克隆或签出。对我来说,将其设置为true(Git 2.2.0/Mac OS X 10.9.5上的默认值)会错误地将5个名称不正常的文件显示为未跟踪。4用双引号括起来。如果我将其设置为false,其中4个被跟踪,但没有双引号的一个仍然未被跟踪。这四个可能是韩国人,而第五个则是乌姆劳特。有什么想法吗?这对我来说很有效,尽管只是在省略了
--global
之后。另请参见作者(2015年7月1日)。(于2015年8月3日合并)