警告:我对 TortoiseHg 及其迁移器一无所知(如您链接到的另一个答案中所述),但是 Mercurial 和 Git 呈现提交的方式之间存在显着差异,特别是在它们如何排序 他们。
提交时间戳
...当有一个分支,其中父母的日期比孩子的日期大时,问题似乎出现了(不要问我是如何做到这一点的;我不知道)。
这并不像人们想象的那么罕见。
除了显而易见的(计算机时钟设置为错误的时间)之外,还存在时区问题(加利福尼亚州的提交,比纽约的提交早了三个小时)。并非所有转换器都能做到这一点,因为这是一个难题。
Mercurial 标签与 Git 标签
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 只有在这些提交对象存在时才有效。绘制图表的任何程序都是错误的(或者仅当您以某种方式指示它不显示这些提交时才正确)。
对此有解释吗?更好的是,在进行转换时有什么方法可以避免它?或者以后有什么办法解决?
以上大概就是为什么;至于如何防止或改变它,这来自为什么:你需要以某种方式捏造日期,以便它们以所需的顺序出现。