windows - Git:在 Windows 中协调两个具有重复名称(大小写不同)的文件夹,同时保留历史记录

标签 windows git version-control path revision-history

我最近发现我的解决方案中有几个文件夹在 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 ö ns 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 眼中的文件,这对操作系统眼中的文件名没有影响; FooBarFoobar这里的名字相同 - 并且继续做事。您的替代方案是重写所有历史记录,追溯到不良配对首次添加到存储库的时间点,方法是将每个“不良”提交复制(稍加修改)到新的和改进的“良好”提交。但这意味着让使用该存储库的每个人都从“糟糕的旧存储库”切换到“新的和改进的良好存储库”。

关于windows - Git:在 Windows 中协调两个具有重复名称(大小写不同)的文件夹,同时保留历史记录,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/47225394/

相关文章:

mysql - 如何使用 mysql 创建 localhost 数据库?

git - 为 tortoiseGit 更改 GIT_SSH 的值

git - 是否可以从另一个 git 存储库中挑选一个提交?

command-line - git中删除上一个分支的快捷方式

c# - 使用 TFS 和 Git 管理同一个项目

windows - 从 linux 终端关闭 Windows 机器

windows - Windows 的 CVDisplayLink 替代品?

git - 如何将具有许多分支的大型 bzr 项目迁移到 git 并过滤历史记录

windows - 获取给定 Windows 消息标识符的数值

git - 应该在哪里创建 git 存储库?