我最近发现我的解决方案中有几个文件夹在 Git 中有两个不同的路径(GitHub 显示两个单独的文件夹),其中一个是 FooBar
另一个是 Foobar
。这是因为有些文件使用前一个文件夹名称作为其路径进行注册,有些则使用后者。
这是通过将 Git 配置为不忽略大小写在本地(在 Windows 中)发现的: git config core.ignorecase false
我尝试通过删除整个文件夹、提交、然后重新添加文件夹并再次提交来解决此问题。这解决了问题,但是更改路径的文件丢失了其 Git 历史记录。运行gitk
这些文件的新路径仅显示一次提交。运行gitk
违背他们的旧路揭示了他们的整个历史。
下一个刺:使用git mv
移动文件:
git mv Foobar/file.txt FooBar/file.txt
这会产生错误:
fatal: destination exists, source=Foobar/file.txt, destination=FooBar/file.txt
如果我尝试先删除该文件,Git 当然会提示源文件不存在。
然后我发现如果你添加-f
,Git 不会提示目的地已经存在。到mv
命令。但是,在提交重命名后,gitk
表明历史无论如何都被切断了!
我什至尝试做 three step dance described here但这只是执行 -f
的另一种方式。结果相同。
基本上我只想从 Foobar/file.txt
移动文件至FooBar/file.txt
以某种方式在不区分大小写的操作系统中,同时保留 Git 历史记录。这可能吗?
最佳答案
对于真正的问题没有简单的解决方案。
在 Git 中,文件没有历史记录。提交有历史——或者更准确地说,提交就是历史。这就是所有的历史。让 Git “跟随”一个文件,如 git log --follow <path>
,Git 一次查看一个提交,将每个提交与其父提交进行比较。
如果父项和子项之间的差异显示父项包含名为 parent/path/to/pfile
的文件并且子级包含一个名为 child/path/to/cfile
的文件并且这两个文件的内容在这两次提交中是“足够相似”(这里必须满足几个条件),那么,在 Git 的“眼睛”中,父到子的转换代表了一个重命名该文件。所以在这一点上,git log --follow
,一直在寻找child/path/to/cfile
,开始寻找 parent/path/to/pfile
.
没有--follow
, git log
不执行这种特殊的“查找重命名”操作...并且一般来说,Git 认为任何具有任何字节级差异的路径名都代表不同的文件。换句话说,不会发生大小写折叠和 UTF-8 标准化。例如,考虑单词 schön
,可以表示为 s
c
h
ö
n
或s
c
h
o
组合-¨
n
。我们可以在 Linux 机器上使用这两个不同的 UTF-8 样式名称创建两个不同文件。运行ls
将显示两个名称相同的文件:
$ cat umlaut.py
import os
p1 = u'sch\N{latin small letter o with diaeresis}n'
p2 = u'scho\N{combining diaeresis}n'
os.close(os.open(p1.encode('utf8'), os.O_CREAT, 0o666))
os.close(os.open(p2.encode('utf8'), os.O_CREAT, 0o666))
$ python umlaut.py
$ ls
schön schön umlaut.py
Git 非常乐意单独存储这两个文件。然而,MacOS 拒绝允许这两个文件共存,就像 Windows 一样(就此而言,默认情况下 MacOS 也拒绝允许这两个文件共存 Foobar
)和FooBar
共存。
让 Git 将文件存储在新提交的新字节序列下,并保留历史记录,但它不是您想要保留的历史记录。但是存储库中已经存在的历史记录已经不是您想要保留的历史记录。
实际上,您可能应该只重命名 Git 眼中的文件,这对操作系统眼中的文件名没有影响; FooBar
和Foobar
这里的名字相同 - 并且继续做事。您的替代方案是重写所有历史记录,追溯到不良配对首次添加到存储库的时间点,方法是将每个“不良”提交复制(稍加修改)到新的和改进的“良好”提交。但这意味着让使用该存储库的每个人都从“糟糕的旧存储库”切换到“新的和改进的良好存储库”。
关于windows - Git:在 Windows 中协调两个具有重复名称(大小写不同)的文件夹,同时保留历史记录,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/47225394/