【问题标题】:Strange git state after migration from Mercurial从 Mercurial 迁移后出现奇怪的 git 状态
【发布时间】:2016-05-24 06:48:05
【问题描述】:

我一直在尝试使用this answer 中提供的方法将我的 Mercurial 存储库迁移到 git。

存储库头部周围的一切似乎都运行良好。我可以看到我的标签、我的分支等,一切都很好,一切似乎都在正确的位置。但是,在 Sourcetree 中检查它时,我发现了一些奇怪的东西。例如,这是我在存储库底部看到的:

如您所见,在初始提交之前似乎有很多分支。

我已经探索了其中的一些,似乎当有一个分支,其中父母的日期比孩子的日期更早时出现了问题(不要问我是如何做到的;我不知道)。这是上图中最右边的绿线的示例:

我还发现有些线从图表底部到没有任何提交的合并,因此,在提交中它没有正确显示合并的来源:

对此有解释吗?更好的是,在进行转换时有什么方法可以避免它?或者以后有什么办法解决?

【问题讨论】:

    标签: git mercurial


    【解决方案1】:

    警告:我对 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 只有在这些提交对象存在时才有效。绘制图表的任何程序都是错误的(或者仅当您以某种方式指示它不显示这些提交时才正确)。

    对此有解释吗?更好的是,在进行转换时有什么方法可以避免它?或者以后有什么办法解决?

    以上大概就是为什么;至于如何防止或改变它,这来自为什么:你需要以某种方式捏造日期,以便它们以所需的顺序出现。

    【讨论】:

    • 感谢您如此详尽的解释!我认为解释是在“绘制图表的任何程序都做得不正确”,因为所有提交似乎都正确设置了父母。事实上,我已经用git log --graph(加上一些选项)绘制了图表,它显示得很好。再次感谢。
    • 我刚刚发现 SourceTree 有一个选项可以在“日期顺序”和“祖先顺序”之间切换......在祖先顺序中显示就好了。就是这样……
    猜你喜欢
    • 1970-01-01
    • 2020-11-23
    • 1970-01-01
    • 2015-12-03
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2013-12-24
    • 1970-01-01
    相关资源
    最近更新 更多