Git大小写陷阱:当README.md遇上readme.md

文章目录

这是一个发生在真实仓库里的故事,主角是两个文件,它们名字一样,只是大小写不同。在Linux上它们相安无事,到了Windows上,战争开始了。

故事的开始

某天,我在Windows电脑上执行了git pull

复制代码
$ git pull
Fast-forward
 README.md | 1 +
 readme.md | 1 +
 2 files changed, 2 insertions(+)
 create mode 100644 README.md
 create mode 100644 readme.md

看起来很正常,拉取了两个文件。然后我看了看当前目录:

复制代码
$ ls
readme.md
...

等等,不是拉了两个文件吗?怎么只有一个?

灵异事件调查

我决定深入调查:

复制代码
$ git show HEAD:README.md
uppercase: just for test

$ git show HEAD:readme.md
lowercase: just for test

两个文件,内容不同,都存在于Git仓库中。

再看一眼Git状态:

复制代码
$ git status
Changes not staged for commit:
    modified:   README.md

破案了! Git认为README.md被修改了,但我的工作目录里只有readme.md

真相只有一个

事情的真相是这样的:

角色 行为
Linux文件系统 README.mdreadme.md 是两个不同的文件 ✓
Windows文件系统 README.mdreadme.md 是同一个文件 ✗
Git对象库 存了两个blob,内容都保存着 ✓
Git索引 记录了两个条目 ✓
Git checkout 按顺序写文件,后写的覆盖了前写的 ¯\(ツ)

是的,Git没有报错,它就这么默默地把两个文件写到了同一个路径上,后写的覆盖了前写的。

画个图:

复制代码
.git/objects/          工作目录 (Windows)
┌─────────────────┐    ┌─────────────────┐
│ blob: "upper..."│    │                 │
│ blob: "lower..."│    │ readme.md       │ ← 最后写的
└─────────────────┘    └─────────────────┘
     ↑                        ↑
   Git都知道               Windows只认一个

core.ignorecase=true 是什么?

你可能会问:不是说Git有core.ignorecase=true这个配置吗?

是的,这个配置告诉Git:在比较文件名时忽略大小写

但问题是,这个配置不会阻止你创建两个只有大小写不同的文件 。它只是让Git在检测文件变更时,把README.mdreadme.md当成同一个文件来处理。

所以这个配置反而让情况更混乱:

  • 远程仓库有两个文件(Linux用户创建的)
  • Windows用户拉取时,Git不报错
  • 工作目录只剩一个文件
  • Git状态显示"modified"

如何避免这个坑

1. 检查是否有大小写冲突

bash 复制代码
git ls-files | sort -f | uniq -di

这个命令会列出所有只有大小写不同的文件名对。

2. 重命名冲突的文件

bash 复制代码
# 把readme.md重命名为README-lowercase.md
git mv readme.md README-lowercase.md
git checkout -- README.md
git add README-lowercase.md
git commit -m "Rename to avoid case conflict on Windows"

3. 团队约定

最佳实践:永远不要创建只有大小写不同的文件名

这不是技术问题,是团队协作问题。在跨平台项目中,这就是一个定时炸弹。

总结

平台 大小写敏感 建议
Windows 避免创建冲突文件名
Linux 也别这么干,照顾Windows队友
macOS 默认否 同Windows

记住:Git不会保护你免受文件系统的限制。它只是忠实地记录你让它记录的一切,然后忠实地把一切写到文件系统允许它写的地方。

下次看到git status莫名其妙显示文件被修改,想想是不是大小写的问题。


本文由一个真实的大小写冲突事件改编,该事件就发生在写文档的这个仓库里。

相关推荐
九皇叔叔29 分钟前
Ubuntu 22.04 版本常用设置
linux·运维·ubuntu
南境十里·墨染春水32 分钟前
linux学习进展 线程同步——互斥锁
java·linux·学习
杨云龙UP2 小时前
ODA登录ODA Web管理界面时提示Password Expired的处理方法_20260423
linux·运维·服务器·数据库·oracle
songx_993 小时前
Linux基础2
linux·运维·服务器
longerxin20203 小时前
卸载 CCleaner 失败?用 Revo Uninstaller 彻底清干净(附官方下载 + 详细步骤)
windows
我想要SSR3 小时前
搭建小龙虾过程和坑点
linux·服务器·ai
莫白媛4 小时前
Linux在限制敏感命令下的修改用户密码小白版
linux·运维·服务器
Rcnhtin5 小时前
RocketMQ
java·linux·rocketmq
AC赳赳老秦6 小时前
OpenClaw多平台部署:Windows+Linux跨系统协同,实现全场景覆盖
linux·服务器·前端·网络·windows·deepseek·openclaw
念恒123066 小时前
进程--程序地址空间下篇(进程地址空间)
linux·c语言