不要使用 msysgit 1.9.5,而是尝试适用于 Windows 的最新 Git:
从 Git 2.18 开始, git status
更好地检测重命名(文件和文件夹)
使用 Git 2.33(2021 年第 3 季度),它将更进一步,管理基于内容的重命名检测and目录重命名检测。
但仅限于新的合并策略ORT ("表面上递归的双胞胎").
See commit 3585d0e, commit a492d53, commit 806f832 (30 Jun 2021) by Elijah Newren (newren).
(Merged by Junio C Hamano -- gitster -- in commit d3b88be, 16 Jul 2021)
merge-recursive:处理重命名为自身的情况
Reported-by: Anders Kaseorg
Signed-off-by: Elijah Newren
目录重命名检测可能会导致传递重命名,例如如果历史的两个不同方面各做一半:
A/file -> B/file
B/ -> C/
然后目录重命名检测传递重命名给我们
A/file -> C/file
然而,当 C/ == A/ 时,请注意,这给了我们
A/file -> A/file.
合并递归假设任何重命名D -> E
将有D != E
.
虽然这几乎总是正确的,但上面的情况是一个特殊情况,但事实并非如此。
因此,我们不能执行诸如删除重命名源之类的操作,我们不能假设路径 E 中存在的文件意味着重命名/添加冲突,并且我们必须小心输出中最终出现的阶段。
这个改变感觉有点hackish。
令人惊讶的是,我花了很多时间才找到,并且考虑到合并递归的设计导致它尝试枚举边缘和角落情况的所有组合,并为每个组合提供特殊代码,我担心如果我们可以的话,其他地方还需要其他类似的修复提出正确的特殊测试用例。
也许审计可以排除这种可能性,但我没有精力。
merge-recursive 应该消亡,而且由于它无论如何都会被淘汰,因此狭隘地修复这个特定的错误必须足够好。
Git 2.35(2022 年第一季度)修正了 ort 合并策略中的一个极端情况错误。
See commit d30126c (28 Dec 2021) by Elijah Newren (newren).
(Merged by Junio C Hamano -- gitster -- in commit 2c54104, 10 Jan 2022)
merge-ort:修复重整化和重命名/删除冲突的错误
Reported-by: Ralf Thielow
Signed-off-by: Elijah Newren
Reviewed-by: Derrick Stolee
自从提交a492d53 (merge-ort
:确保我们查阅 df_conflict 和 path_conflicts,2021-06-30,Git v2.33.0-rc0 --merge列于batch #5) (“merge-ort:确保我们协商df_conflict
and path_conflicts",
2021-06-30),当重新规范化处于活动状态并且文件涉及重命名/删除冲突但文件未修改(无论是在重新规范化之前还是之后)时,merge-ort 会遇到断言失败。
在提交之前(或者如果断言被编译出来),merge-ort 会错误合并,忽略重命名/删除冲突,只删除文件。
删除断言,适当修复代码,在代码中留下一些好的注释,并针对这种情况添加测试用例。
Git 2.38(2022 年第 3 季度)修复了长期存在的极端情况错误目录在合并或策略中重命名。
See commit 751e165, commit 3ffbe5a, commit 6dd1f0e, commit 51e41e4, commit 0565cee (05 Jul 2022) by Elijah Newren (newren).
(Merged by Junio C Hamano -- gitster -- in commit e3349f2, 18 Jul 2022)
merge-ort:修复双重重命名和添加/添加冲突的问题
Signed-off-by: Elijah Newren
merge-recursive 和 merge-ort 中都有代码来避免双重传递重命名 (i.e.
一侧重命名目录A/ -> B/
,另一端重命名目录B/ -> C/
),因为这种组合否则会使添加到的新文件变得混乱A/
在第一面并想知道它们最终会进入哪个目录 - 特别是如果有更多重命名,例如第一面重命名C/ -> D/
.
在这种情况下,它只是“关闭”高阶传递情况的目录重命名检测。
另一种看待这个问题的方法是,如果一侧目录重命名中涉及的源名称是另一侧文件的目录重命名操作的目标名称,那么我们就避免了双重传递重命名。
(更具体地说,如果目录在一侧重命名D
想要重命名侧面的文件E
from OLD_NAME
-> NEW_NAME,
和侧面D
已经有一个名为NEW_NAME,
和侧面的目录重命名E
想要重命名 D 面NEW_NAME
-> NEWER_NAME,
然后我们关闭目录重命名检测NEW_NAME
以防止NEW_NAME
-> NEWER_NAME
重命名,并最终导致添加/添加冲突NEW_NAME
.)