bounty将在3小时后过期。回答此问题可获得+250声望奖励。Peter Alfvin希望引起更多人对此问题的关注。
当我试图拉(或 checkout 或挑选)一个提交涉及文件名只在大小写方面改变的文件时,我从git得到了以下错误:
合并将覆盖以下未跟踪的工作树文件
之后它列出了所有只有大小写差异的文件。一个git status
在我的工作目录中什么也没有显示。
在删除了有问题的文件的本地副本后,我能够成功地执行pull
,但我想知道是否有更优雅的方法来解决,或者更好的是,首先 * 避免 * 这个问题。其他在本地机器上使用相同存储库的MacOS上运行的用户没有这样的症状/问题。
4条答案
按热度按时间bqujaahr1#
The
git
utility assumes your filesystem is case-sensitive,因为大多数(如果不是全部的话)Linux和FreeBSD文件系统都是如此。如果您在macOS上操作,默认情况下文件系统不区分大小写。要在macOS上使用
git
,请创建一个新的区分大小写的虚拟宗卷,并与其他宗卷共享相同的APFS分区。请将新的区分大小写卷专门用于
git
存储库工作。如果在此卷上编译应用程序,请根据需要使用其他区分大小写卷上的配置和数据文件对其进行测试。打开“磁盘工具”并点按
+
按钮以创建新宗卷:命名新卷:
将文件存储在此目录中:
vlurs2pr2#
删除本地文件(如in here)是一种解决方案。
首先检查一下
git config --global core.ignoreCase true
是否对您的下一个git pull
有帮助。检查其他用户是否已设置该设置。
jrcvhitl3#
“在MacOS上运行的其他用户在其本地计算机上使用相同的存储库时没有此类症状/问题。”
在不区分大小写的文件系统上:用户磁盘上的文件名记录了用户机器上发生的一系列操作,一旦一个文件在磁盘上创建(可能是因为
git swicth
或git pull
在磁盘上创建了一个新文件,其大小写在git中列出,也可能是因为用户自己命名了该文件),它将保留该大小写。为了说明这一点:在Windows和MacOS上,
mv Readme.md README.md
是一个空操作--即使文件实际上被命名为rEaDmE.md
,它也将保留其初始名称。以类似的方式:如果您在指定文件名为
Readme.md
或README.md
的分支之间切换,磁盘上的文件名实际上不会改变--它将保持最初的名称。所以你可能会在你的磁盘上得到一个repo,其中的文件和你同事的磁盘上的文件不同名,仅仅是因为你在切换到
master
之前碰巧在git pull
分支上。要找出磁盘上的文件名和git中的文件名之间的差异,可以比较
git ls-files
和git ls-files | xargs ls
:(* 注意:* 我手头没有MacOS文件系统,我希望如果磁盘上的文件实际上是大写的,
ls readme.md
将输出README.md
,并且git ls-files | xargs ls
将显示 * 您的文件系统上的名称的实际大小写 *,而不仅仅是重复git ls-files
的输出)在Windows/MacOS上重命名文件的常见解决方法是使用临时名称:
git mv
也是如此:git mv Readme.md README.md
将成功更改 * 存储在git* 中的名称,但不会更改 * 磁盘上的名称 *。您可以:
如果你想让磁盘上的文件名与git中的文件名匹配,你可以使用第一个命令的输出来发出重命名命令。
qcbq4gxm4#
TL;DR
在不区分大小写的FS/OS上,在git repo中重命名区分大小写的文件/目录时遇到问题;请遵循以下3个步骤:
1.确保
git config --global core.ignorecase
不返回任何内容,或者至少返回true
.如果false
- reset为null,那么git可以根据存储库克隆到的文件系统自动检测这个配置。1.在repo中,如果它位于不区分大小写的文件系统(或操作系统)中,请确保
git config core.ignorecase
设置为true
。如果没有或为false,请设置为true。1.更新git到最新版本。
问题是
Git是建立在区分大小写的文件系统之上的,因此兼容性最强。随着git越来越流行,它在区分大小写的文件系统上的应用越来越多,发现的问题和因大小写处理不兼容而打开的bug也越来越多。不要误会我的意思--这些问题 * 已经 *(如果仍然存在-- * 正在 * 解决),但仍然是一条崎岖的道路。
我不建议将整个文件系统格式化为区分大小写,因为这可能会破坏其他期望文件名区分大小写的应用程序。
进步
这只是我个人的看法,但我觉得在过去的15年里,对于git爱好者来说,事情已经发生了巨大的变化,从要求文件系统区分大小写,到git自己更好地(几乎无缝地)处理不区分大小写。
“我为什么要讲这么长的故事?”
可以使用一个特别的方法来解决一个特定的文件重命名问题,但这只是一个变通方法,而不是解决方案。Git应该能够“开箱即用”地处理不敏感的文件系统:
核心.忽略案例
内部变量,它提供了各种变通方法,使Git能够更好地在不区分大小写的文件系统上工作,如APFS、HFS+、FAT、NTFS等。例如,如果目录列表在Git期望的是“Makefile”时找到了“Makefile”,Git将假定它实际上是同一个文件,并继续将其记为“Makefile”。
默认值为false,除非git-clone(1)或git-init(1)在仓库创建时探测并设置core.ignoreCase为true。
Git依赖于您的操作系统和文件系统对此变量的正确配置。修改此值可能会导致意外行为。
当在一个不敏感的环境下克隆或初始化仓库时,Git应该能够自动处理文件/目录的字母大小写重命名。当然,如果仓库包含两个应该共存的路径,这会有问题。只是大小写不同(例如
mypath/myfile.txt
和mypath/MyFile.txt
)-这在不敏感的文件系统上是不可能的。出现问题的另一个原因是,如果存储库是在以下情况下首次克隆/初始化的-敏感FS,但后来物理移动(mv
/cp
)到不敏感FS;在这种情况下,将存储库的core.ignorecase
配置设置为true会使情况更好。尽管如此,尽管git“应该”能够处理这样的情况,但保持git的最新是很重要的。当问题被发现时,更新的版本会解决它们,使体验更加流畅。这些不是以任何方式被视为“耻辱名单”,而是为了显示维护人员的参与以及他们在无缝支持不区分大小写的FS/OS方面所实现的目标。并让那些设法阅读到目前为止的人相信软件更新的重要性:
***已在Git v2.31.1中修复:**修复了不区分大小写的系统上“git mv”中的一个角大小写错误,该错误是在2.29版本中引入的。
***已在Git v2.21.0中修复:**在不区分大小写的文件系统上,我们无法比较绝对路径名中工作树目录之上的路径部分,该问题已得到更正。
***已在Git v2.20.0中修复:**在不区分大小写的文件系统上,如果一个项目包含两个路径名仅大小写不同的文件,则对该项目运行“git clone”会导致其中一个文件丢失,因为底层文件系统无法同时保存这两个文件。系统会尝试检测这种情况并发出警告。
*在Git v2.17.6中修复:CVE编号2021-21300:
在支持符号链接的不区分大小写的文件系统上,如果Git被全局配置为应用具有延迟能力的clean/smudge过滤器(例如Git LFS),Git可能会在克隆过程中被欺骗运行远程代码。
***已在Git v2.16中修复:**递归合并策略的内部代码没有做好充分准备,无法看到一个路径被重命名以尝试覆盖另一个仅在大小写不敏感的系统上不同的路径。这在当前代码中并不重要,但一旦重命名检测逻辑开始从移动到某个目录的附近路径中获取提示,并沿着移动一个新路径,这就开始重要了。
***已在Git v2.1中修复:**在不区分大小写的文件系统上,合并递归错误地删除了要重命名为除了大小写不同之外名称相同的文件。
***已在Git v1.8.3中修复:**在文件系统不区分大小写的平台上,跟踪哪些目录名是Git已知的代码可能会在这些路径名之间发生哈希冲突时混淆,并将永远循环。