40.2 文件名大小写问题

Linux、Solaris、BSD及其他类Unix操作系统使用的是大小写敏感的文件系统,而Windows和Mac OS X(默认安装)的文件系统则是大小写不敏感的文件系统。即用文件名README、readme及Readme(混合大小写)进行访问,在Linux等操作系统上访问的是不同的文件,而在Windows和Mac OS X上则指向同一个文件。换句话说,不同的文件README、readme及Readme在Linux等操作系统上可以共存,而在Windows和Mac OS X上,这些文件只能同时存在一个,另外的会被覆盖,因为在大小写不敏感的操作系统看来,这些文件是同一个文件。

如果在Linux上为Git版本库添加了两个文件名仅大小写不同的文件(文件内容各不相同),如README和readme。当推送到服务器的共享版本库上,并在文件名大小写不敏感的操作系统中克隆或同步时,就会出现问题。例如在Windows和Mac OS X平台上执行git clone后,在本地工作区中出现两个同名文件中的一个,而另外一个文件会被覆盖,这就会导致Git对工作区中的文件造成误判,在提交时会导致文件内容被破坏。

当一个项目存在跨平台开发的情况时,为了避免这类问题的发生,在一个文件名大小写敏感的操作系统(如Linux)中克隆版本库后,应立即对版本库进行如下设置,让版本库的行为好似对文件名大小写不敏感。


$git config core.ignorecase true


Windows和Mac OS X在初始化一个版本库或克隆一个版本库时,会自动在版本库中包含配置变量core.ignorecase为true的设置,除非版本库不是通过克隆而是直接从Linux上拷贝而来的。

当版本库包含了core.ignorecase为true的配置后,文件名在文件添加时便被唯一确定。如果之后修改文件内容的同时又修改了文件名中字母的大小写,只会被视为对文件内容的修改,执行提交不会改变文件名。如果对添加文件时设置的文件名的大小写不满意,确实需要对文件重命名,对于Linux来说很简单,直接运行git mv命令显式地对文件进行重命名操作。例如执行下面的命令就可以将changelog文件的文件名修改为ChangeLog。


$git mv changelog ChangeLog

$git commit


但是对于Windows和Mac OS X却不能这么操作,因为Git会拒绝这样的重命名操作:


$git mv changelog ChangeLog

fatal:destination exists,source=changelog,destination=ChangeLog


而需要像下面这样,先将文件重命名为另外的一个名称,再执行一次重命名改回为正确的文件名,如下:


$git mv changelog non-exist-filename

$git mv non-exist-filename ChangeLog

$git commit