我一直在尝试使用this answer中提供的方法将我的Mercurial存储库迁移到git。
存储库头部周围的一切似乎都运行良好。我可以看到我的标签,我的树枝等等都很好,一切似乎都在正确的地方。但是,在Sourcetree中检查它时,我发现了一些奇怪的东西。例如,这就是我在存储库底部看到的内容:
正如您所看到的,在初始提交之前,有许多分支似乎来自。
我已经探索了其中的一些,似乎问题出现在有一个分支,父母的日期比孩子的年龄大(不要问我怎么设法做到这一点;我不知道)。以下是上一张图片中最右边绿线的示例:
我还发现一些行从图的底部到没有任何提交的合并,因此,在提交中它没有正确显示合并的来源:
对此有解释吗?更好的是,在进行转换时有什么办法可以避免它吗?或者之后以任何方式修复它?
答案 0 :(得分:1)
...当有一个父母的日期比孩子更早的分支时,似乎问题出现了(不要问我是怎么做到的;我不知道)。
这并不像人们想象的那么罕见。
除了显而易见的(计算机时钟设置为错误的时间),还存在时区问题(在加利福尼亚提交,比纽约提交的提前3小时)。并非所有转换器都能做到这一点,因为这是一个难题。
Mercurial标签存储在一个文件(.hgtags
)中,然后将其作为单独的提交存储(带有不幸的副作用,检查标记版本会使标记本身不可见,因为标记用于提交有.hgtags
缺少标签的人。看起来你的转换器正在存储Mercurial标签提交为Git提交:不是特别令人惊讶(这样会更容易)但也不是特别理想(如果可能的话,Mercurial标签应该转换为Git带注释或轻量级标签)。
默认情况下,Mercurial按存储库中的绝对提交编号对提交进行排序。 (对于hg
命令,这是正确的; TortoiseHg之类的外部程序是否跟随它们。)这意味着提交上的日期戳与呈现顺序完全无关。 Mercurial只能执行此操作,因为单个存储库中的每个提交在该存储库中都具有本地唯一的索引号,以及在所有克隆中具有相同的全局唯一标识符(SHA-1哈希)。 (不同克隆的本地唯一数字索引不一定相同,即使它们包含相同的提交,因为它取决于这些提交进入所有克隆的顺序。更具体地说,两个克隆开始相同,但随后如果克隆A按此顺序获取提交a111111和a222222,并且克隆B按照a222222-then-a111111的顺序获取它们,则这两个提交的索引号将采用相反的顺序。)
默认情况下,Git按日期排序,在旧提交之前显示更新的提交。在绘制图形时,此排序顺序会有所修改:在这种情况下,Git仍按日期排序,但adds a topological sort constraint:
--topo-order
在显示所有子项之前不显示父项,并避免在多行历史记录中混合显示提交。
例如,在这样的提交历史中:
---1----2----4----7 \ \ 3----5----6----8---
其中数字表示提交时间戳的顺序,
git rev-list
和--date-order
的朋友按时间戳顺序显示提交:8 7 6 5 4 3 2 1.
--topo-order
,他们会显示8 6 5 3 7 4 2 1(或8 7 4 2 6 5 3 1);一些较旧的提交会在较新的提交之前显示 避免显示来自两个平行开发轨道的提交混合 在一起。
并非所有的图形程序都使用相同的约束:特别是gitk
执行自己的提交排序(它默默地吃--topo-order
以避免将其传递给git rev-list
)。
(一个相关的问题是Mercurial提交只有一个时间戳,而Git提交有两个:作者时间戳和提交者时间戳。虽然你在hg-to-git方向转换,但我会假设git-commit-generator只是设置两个时间戳以匹配Mercurial时间戳。如果不是,那么也可能会影响它。)
我还发现一些行从图的底部到合并而没有任何提交......
这在Git中是不可能的,因为合并只能通过在合并中至少有两个父提交ID来存在,并且父ID只有在存在这些提交对象时才有效。无论是什么程序绘制图形都是错误的(或者只有在某种程度上,你指示它不显示那些提交时才正确)。
对此有解释吗?更好的是,在进行转换时有什么办法可以避免它吗?或者之后以任何方式修复它?
以上可能是为什么;至于如何防止或改变它,来自为什么:你需要以某种方式捏造日期,以便它们以所需的顺序出现。