写在前面
在项目开发的时候,一个99%的人都会遇到的问题:就是git作为版本控制工具。 文件名、文件大小写的问题。 因为我对git的理解不够深入导致花费了不少时间来排查,同时也体会到好的规范比好的技术其实更重要。
搭建环境
-
新建gitee仓库
-
执行创建git仓库的命令
搭建测试案例
- 新建一个文件夹testfolder,作为测试文件夹,并且里面有一个innertestfile.txt文件,里面有内容,作为测试文件
- 新建一个文件testfile.txt,并且添加内容,作为测试文件 查看git status,
- 将testfile.txt添加到git仓库中 执行
add .
命令,将testfile.txt添加到git仓库中 执行commit -m "add testfile.txt"
命令,将testfile.txt提交到git仓库中 此时远程仓库的情况:
问题复现
- 现在修改testfile.txt文件,将testfile.txt修改为Testfile.txt,然后执行git status命令,发现git没有检测到文件的变化,因为git默认忽略大小写,所以git认为Testfile.txt和testfile.txt是同一个文件,所以没有检测到变化。
2. 现在在更改了文件名的情况下,修改文件的内容。
3. 然后提交,发现提交成功,但是远程仓库的文件名没有变化,还是testfile.txt,而本地仓库的文件名已经变成了Testfile.txt。
- 如果执行
git config core.ignorecase false
,设置Git的规则为区分大小写(大小写敏感),此时执行git status
,显示有一个新的文件Testfile.txt
- 把这个新增的文件提交到远程仓库,执行
git add .
,然后执行git commit -m "add Testfile.txt"
,然后执行git push
,发现远程存在两个文件,一个是testfile.txt,一个是Testfile.txt。
- 此时如果同事现在拉取这个仓库,因为操作系统(mac和windows)是不支持文件名大小写区分的,所以他会发现,远程仓库有两个文件,一个是testfile.txt,一个是Testfile.txt,他会很懵逼,不知道该用哪个文件,所以这里我的mac系统会选择删除Testfile.txt,保留testfile.txt。
- 但是如果是linux操作系统,就会保留着两个文件,如下:
这里就遇到了两个问题:
- git 在团队开发中的规范问题,如果团队中有人修改了文件名的大小写,应该如何正确修改。
- git远程仓库的两个文件,在同事下次拉取仓库的时候,会报错,存在风险;需要删除远程仓库中不需要的文件。(这个问题本来可以在修改文件名的时候就解决,但是因为之前没有意识到,所以导致这个问题)
解决方法
对于本地的文件需要修改文件名的大小写
- 执行
git config core.ignorecase false
命令,将git的忽略大小写功能禁用。 - 对于需要修改文件名的大小写的情况,需要执行
git mv testfolder/innertestfile.txt testfolder/Innertestfile.txt
,将文件名的大小写修改正确,这里把testfolder目录下的innertestfile.txt修改为Innertestfile.txt。 - 这时候,执行
git status
命令,发现git已经检测到文件的变化,是一个renamed的变化,并且存入了暂存区。
- 这时候
git push
,发现远程仓库的文件名已经变成了Innertestfile.txt,而不是innertestfile.txt。
对于本地的文件需要修改目录名的大小写
这里把根目录下的testfolder目录改成了Testfolder目录,和修改文件名的大小写有点区别。
bash
# 将本地的 test 目录删掉,并生成一个新的目录 tempfolder
$ git mv testfolder tempfolder
# 将 tempfolder 目录改成 Testfolder 目录。此时,项目中只会存在 Testfolder 目录,不会存在 testfolder 目录。目标达成。
$ git mv tempfolder Testfolder
执行git status命令,发现在暂存区有reanmed类型的修改,然后直接push到远程,就可以了。
对于远程已经有了大小写不同的文件,如何解决
- 直接在文件夹中删除大小写不同的文件,然后重新添加正确的文件名,然后提交到远程仓库,例如这里需要删除远程仓库的A和a文件中的a文件。
- 使用
git ls-files
命令查看所有已经被 Git 跟踪的文件;这里可以看到A和a文件都被跟踪了。 - 使用
git rm a
命令,将文件a的跟踪从 Git 仓库中删除。- 执行完这个命令后可能会删除本地的A文件,这是你之前已经执行过
git rm a
命令,所以本地已经没有a文件了,所以会删除A文件。 - 可以使用
git restore A
命令,将A文件恢复到最近一次提交的状态。
- 执行完这个命令后可能会删除本地的A文件,这是你之前已经执行过
- 紧接着commit,push后,远程仓库的a文件就删除了,同时两个仓库都是只有A文件。
对于目录:
- 执行
git rm -r a
命令,将目录a的跟踪从 Git 仓库中删除。 - 紧接着commit,push后,远程仓库的a目录就删除了,同时两个仓库都是只有A目录。
最后
关于是否区分大小写的补充说明
我们知道:针对文件/文件夹,Windows系统和Mac系统通常是不区分大小写的;Linux系统是区分大小写的; Git默认是不区分大小写的,也可以通过改配置项,改为区分大小写。
不分区大小写,也有它的好处,比如:文件夹/文件的路径,很多时候就代表了网站地址、页面url的路径。而网站地址也是不区分大小写的,这是很关键的原因之一。
是否需要开启git的忽略大小写功能的探讨
执行git config --global core.ignorecase false
,全局设置 大小写敏感。这样下次修改了文件的时候,就会有感知,开发者就能看到修改。
在开发中,开发者对修改的文件或者目录在git status中文件名大小写修改没有感知,是很危险的,所以推荐使用命令git config core.ignorecase false
修改配置。并且要切记,在修改完了之后,要记得把原来的文件使用git rm <原文件>
命令删除掉。
撤销未暂存的更改的命令
如果您想撤销对 testfile.txt 的删除操作(这个文件还没有被暂存),您可以使用以下命令:
bash
git restore testfile.txt
这个命令会将 testfile.txt 恢复到最后一次提交的状态,撤销您在工作目录中对它的删除。
查看所有跟踪的文件命令
您可以使用 git ls-files 命令来列出所有已经被 Git 跟踪的文件:
bash
git ls-files
这个命令会列出仓库中所有当前被跟踪的文件。
git mv命令
- git mv 就相当于运行了下面三条命令:
bash
$ mv README.md README
$ git rm README.md
$ git add README
总结
- 良好的开发规范,可以避免很多不必要的麻烦。
- 推荐在一个仓库修改配置
git config core.ignorecase false
的值,这样,在这个仓库中,文件名的大小写是敏感的,可以避免修改文件大小写git监测不到的问题。 - 如果需要重命名一个文件或者目录的大小写,推荐使用
git mv <旧文件名> <新文件名>
命令,而不是直接在操作系统提供的命令来删除文件;对于目录,可以加上-r
参数。(这句话推荐加入团队的开发规范中)
参考
代码仓库地址:
参考: