来自合并子库的多个分支的合并历史记录

时间:2018-08-17 20:08:39

标签: merge mercurial

我从一个Mercurial存储库开始,该存储库具有多个要合并到其中的子存储库,好像它们一直是主存储库的一部分。首先,它们不应该成为子存储库。

我整理了一个将旧历史转换为单个存储库的过程:

  1. 进行一个子存储库,并使用--filemap对其进行转换,以将所有内容移动到一个子目录中,该目录的名称应为该子目录的最终目录,如此处所述:Join multiple subrepos into one and preserve history in Mercurial
  2. 在此处使用Clay Lenhart的答案从每个存储库中获取修订版本列表:Is it possible to manually change/reorder the revision numbers (provided topology remains the same)?
  3. 按日期对所有要合并的存储库中的所有修订进行排序。
  4. 将每个修订版本一个一个地拉到一个新的存储库中。
  5. 使用python脚本对生成的存储库进行hg转换,如此处所述:https://www.mercurial-scm.org/wiki/ConvertExtension#Customization,以去除对.hgsub和.hgsubstate文件中子存储库的引用
  6. 手动合并分支。

我剩下的问题是历史记录不可用,即我无法返回并更新到特定版本,因为每个分支只有自己的数据。假设我的主仓库是A,子仓库是B和C:如果我更新到分支A的历史记录,则没有分支B或分支C的文件,如果我更新到分支B的历史记录,则它没有来自分支A或分支C的文件。

我想要的是一种将整个历史合并在一起的方法,因此它主要是一个分支,并且所有分支中的文件都出现在每次提交中。有没有一种方法可以将其转换,以便合并所有分支的历史记录,而不仅仅是在最后合并一次?

2 个答案:

答案 0 :(得分:1)

虽然我没有为您准备的固定流程,但我可以告诉您问题出在哪里,这是步骤3-6。您想做的是:

  1. 列出所有子项目中的所有修订,使用超级项目/主存储库控制将哪些修订组合在一起的顺序。 (您可以在第4步中即时执行此操作。)

  2. 根据步骤3中获得的顺序,从下一个存储库中引入(拉出)下一个修订。如果超级项目表示下一个提交使用子项目A的修订版41和版本97的版本,子项目B和子项目C的第11版,这是要引入的三个项目。然后将它们折叠成一个不引用任何子项目的版本(例如,在合适的情况下使用hg histedit)。

没有步骤5,也没有步骤6,因为此时没有要合并的内容:合并发生在步骤4中。

答案 1 :(得分:1)

我现在有一个工作流程。而不是对每个步骤都执行拉力-

  1. 首先确定从每个存储库导入的总体顺序。 []中的内容是变量。
  2. (在源存储库中,导出更改集):hg export --git -r [OldID] -o [TempPath] \ patch [OldID]
  3. (在目标存储库中,选择父项):hg update --clean [ParentID]
  4. (在目标存储库中,导入更改集):hg import [TempPath] \ patch [ID] --import-branch --bypass
  5. (在目标存储库中,获取节点以供以后使用):hg log -T“ {rev} {node}” -r [NewID]

之所以起作用,是因为该补丁不包含完整的版本信息,而仅包含已更改的信息。它不希望父级与其从中导出的位置匹配,而只是匹配您要修补的文件。而且由于每个修补程序仅影响来自一个存储库中一个分支的文件,因此这是完全合理的假设。

作为合并的变更集有些棘手。我必须编辑补丁文件以使其源节点ID与新导入的节点ID匹配。这就是为什么我们必须在上面的步骤5中捕获节点ID的原因。只要使用--exact,就可以导入合并变更集,但除非补丁文件中的3个节点与存储库中的实际节点相匹配,否则该合并变更集将不起作用。

因此,在合并的情况下,请在上述步骤2之后修改补丁文件,以使每个“#父级”与目标存储库中的正确父级节点ID匹配。然后,在导入之后,再次更新补丁文件,这次用导入的节点ID替换“#Node ID”。

这时,补丁文件应该具有所有3个准确的节点ID,并且可以使用“ hg import --exact --bypass”。这是您第二次导入补丁,它将覆盖您已经导入的现有节点,但会将其标记为适当节点之间的合并。

另一个棘手的部分是确保正确地合并了合并。每个合并都是根据1个分支合并到另一个分支来定义的。如果选择错误的父级,合并将失败。因此,我们将主分支定义为所有其他分支合并到的分支。将两个存储库合并在一起时,您必须从技巧开始,然后沿着主分支回到起点。每个存储库中只有主要分支应该串联在一起,而其他分支则保持独立。