Git 的大小写敏感设置

Git 的大小写敏感设置

Neet 1,242 2022-05-18

1. Git 中的大小写敏感设置

Windows 和 MacOS 在正常情况下均对 大小写不敏感 (case-insensitive),即对它们来说,foo.jsFoo.js 是同一个文件。

而 Git 中对文件目录或文件名大小写敏感的设置字段 core.ignorecase 默认为 false,但通过 git initgit clone 创建仓库时,Git 会自动根据操作系统的文件系统,自动检测并设置。换句话说,在 Windows 和 MacOS 上,项目级别 上的 Git 设置里,core.ignorecase 默认设置是 true

Git 的配置优先级在 Windows 和 MacOS 上略有不同,但 项目级别 的配置(在仓库目录下的 .git/config 文件内)的优先级均是最高的。

Git 中的大小写敏感设置方式如下:

# 项目级别设置(true 大小写不敏感,false 大小写敏感)
git config core.ignorecase false
# 全局设置(true 大小写不敏感,false 大小写敏感)
git config --global core.ignorecase false

如果想查看某一项配置在当前项目中生效的值,可以直接使用 git config <config-name> 查看输出,如查看大小写是否敏感,就是 git config core.ignorecase,加上 --show-origin 选项,还可以查看该配置来自于哪一个级别的配置文件,如 git config --show-origin core.ignorecase

2. 大小写不敏感带来的问题

Git 对大小写不敏感会带来一个问题,当仓库中跟踪的文件 Foo.js 如果被更名为 foo.js 后,Git 是不会检测到文件变动的。

2.1 错误的解决方式

在遇到修改文件名大小写后,Git 没有检测到文件变动后,如果直接将 Git 的大小写敏感配置设置为 大小写敏感,会发现 Git 检测到 新增 了修改后的文件。但要注意,这时候 Git 并没有 删除修改前的文件

如果直接对修改进行提交,就会出现一个奇怪的现象:Git 远程仓库中,会同时存在 大写名称的文件小写名称的文件。同时,其他协作人员(使用早期版本的 Git 时)如果拉取了改动,会发现 本地的文件名并没有发生变动

经过测试,2.31.1 的 Git 其他人同步改动后会显示修改后的文件,但 2.24.1 的 Git 同步改动后,本地文件不会发生变化。但是不管 Git 版本是否变动,远程仓库 中均有两份文件,这是我们不希望看到的。

2.2 如何修正错误

幸运的是,上文带来的问题并非没有解决方式,解决的办法也很简单:

  1. 团队成员 A 对已经存在大小写重名的文件进行重命名,保留其中一个版本,提交到 Git 仓库
  2. 其他人同步成员 A 的修改

但这里需要注意的是,重命名文件这个步骤,需要使用 Git 命令 来完成,直接修改文件管理器内的文件名是不行的。

# 修改已追踪的文件的文件名
git mv <source-filename> <target-filename>
# 或直接将要弃用的文件从 Git 删除
git rm --cached <deprecated-file>

如果 git mv 会提示目标文件已存在,可以先将原文件用 git mv 重命名为一个中间文件名,再用 git mv 重命名为目标文件名,或直接使用 git mv -f 强制改名。

其他成员同步更改后,会发现文件已被删除,实际上要保留的文件会被执行一个 未提交 的删除操作,直接将暂存区里的删除操作还原即可。

3. 最佳实践

那么应该如何设置 Git 的大小写敏感呢?以及当文件名的大小写情况发生变化,应该如何在 Git 同步?

对于 Git 的大小写设置,从 Git 本身的角度来看,跟随系统设置 是绝大多数情况下 Git 自身不会出现错误的选项。至于会不会影响到业务,Git 更希望是交由开发者自己把控,毕竟 Git 只是一个版本控制工具。因此建议可以不对 core.ignorecase 进行修改。

如果需要对 Git 追踪的文件的大小写进行修改,需要使用上文提及的 git mv 命令,这是避免出现奇怪的错误以及同步情况异常的根本解决办法。

参考文档


# Git