20

过去(这里这里)有几个关于 Hg 子回购依赖的问题,但接受的答案似乎并没有解决我的问题。

我的一个项目有4个依赖:A、B、C、D。D依赖A、B、C;并且 B 和 C 依赖于 A:

A、B、C、D 的依赖图

我想使用 Hg 子存储库来存储它们,这样我就可以跟踪它们所依赖的每个版本。这是因为,当我在这个项目中使用 A、B、C 和 D 时,其他项目只需要 A 和 B。因此,B 和 C 必须独立于 D 跟踪他们需要的 A 版本。同时,在我的应用程序中,给定版本 D 引用的 B 和 C 版本必须始终使用与给定版本的 D (否则它会在运行时倒下)。我真正想要的是允许它们在同一个目录中作为兄弟姐妹相互引用——即 D 的 .hgsub 如下所示,B 和 C 看起来像第一行。

..\A = https:(central kiln repo)\A
..\B = https:(central kiln repo)\B
..\C = https:(central kiln repo)\C

然而这似乎不起作用:我明白为什么(给人们足够的绳索来吊死自己很容易)但它很遗憾,因为我认为它是我依赖的最巧妙的解决方案。我已经阅读了一些建议的解决方案,我将快速概述它们以及为什么它们不适合我:

  1. 包括副本作为嵌套子目录,将这些作为 Hg 子存储库引用。这会产生以下目录结构(我已经删除了 A、B、C、B\A、C\A 的主要副本,因为我可以接受在 \D 中引用副本):

    • project\(所有主要项目文件)
    • 项目\D
    • 项目\D\A
    • 项目\D\B
    • 项目\D\B\A
    • 项目\D\C
    • 项目\D\C\A

    这种方法的问题:

    • 我现在在磁盘上有 3 个 A 副本,所有这些都可以有独立的修改,必须在推送到中央仓库之前同步和合并。
    • 我必须使用其他机制来确保 B、C 和 D 引用相同版本的 A(例如 D 可以使用 v1 而 D\B 可以使用 v2)
  2. 一种变体:使用上述但指定 .hgsub 的 RHS 以指向父副本中的副本(即 B 和 C 应具有以下 .hgsub):

    A = ..\A
    

    这种方法的问题:

    • 我的磁盘上还有三个副本
    • 我第一次克隆 B 或 C 时,它会尝试从“..\A”中递归地提取 A 的引用版本,这可能不存在,可能会导致错误。如果它不存在,它不会提供关于应该在哪里找到 repo 的任何线索。
    • 当我对更改进行递归推送时,D\B\A 中的更改不会进入共享中央存储库;他们只是被推到 D\A 上。因此,如果我连续推送两次,我可以保证所有更改都将正确传播,但这完全是一个骗局。
    • 同样,如果我进行(手动)递归拉取,我必须正确获取订单以获取最新更改(即在拉取 D\B\A 之前拉取 D\A)
  3. 使用符号链接将文件夹 \D\B\A 指向 D\A 等。

    这种方法的问题:

    • 符号链接不能在 Hg 存储库本身中编码,因此每次团队成员克隆存储库时,他们必须手动/使用脚本重新创建符号链接。这可能是可以接受的,但我更喜欢更好的解决方案。另外(个人喜好)我发现符号链接非常不直观。

这些是最好的可用解决方案吗?我的初始 .hgsub (见顶部)是一个梦想,或者有什么方法可以请求/实现这个改变?

更新以更好地解释 A、B、C、D 的更广泛使用

4

2 回答 2

5

与其尝试通过 Mercurial(或任何 SCM)来管理您的依赖项,不如尝试使用依赖项管理工具,例如Apache Ivy

使用基于 Ivy 的方法,您没有任何子存储库,您只有项目 A、B、C 和 D。A 生成一个工件(例如 .jar、.so 或 .dll 等),即发布到带有版本的工件存储库(基本上是您保存构建工件的地方)。然后,项目 B 和 C 可以依赖于 A 的特定版本(通过每个项目中的 ivy.xml 文件控制),Ivy 将从工件存储库中检索该版本。项目 B 和 C 还生成发布到您的存储库的人工制品。项目 D 依赖于 B 和 C,并且可以告诉 Ivy 以传递方式检索依赖关系,这意味着它将获取 B、C 和 A 的工件(因为它们依赖于 A)。

Apache MavenGradle可以使用类似的方法(后面使用 Ivy)

主要优点是:

  • 它非常清楚项目正在使用的每个组件的版本(有时人们忘记检查.hgsub,所以他们不知道他们正在使用 subrepos),
  • 它使更改依赖项目变得不可能(因为您正在使用工件,而不是代码)
  • 它使您不必重新构建依赖项目并不确定您使用的是什么版本。
  • 使您免于拥有其他项目使用的多个冗余项目副本。

编辑:在使用 Mercurial 和 Eclipse 的项目功能子模块的最佳实践中,类似的答案略有不同?

于 2011-09-26T14:40:52.200 回答
2

您说您想跟踪他们各自依赖的版本,但您也会对在 B、C 和 D 之间共享的 A 的单个副本感到满意。这些是互斥的 - 对于 A 的单个副本,对 A 的任何更改都会导致 B、C 和 D 的每个 .hgsub 发生更改,因此版本控制没有独立性(因为所有 B、C 和 D 都将在更改 A 后提交)。

拥有单独的副本也会很尴尬。如果您进行的更改会影响 B 的 A 副本和 C 的副本,然后尝试推送整个结构,对(比如说)B 的更改将成功,但对 C 的更改将失败,因为它们需要与您刚刚推送的更改合并B、避免产生新的磁头。这将是一种痛苦。

我会这样做(也许有更好的方法)的方法是创建一个 D 存储库,其中包含 A、B 和 C 的子存储库。B 和 C 中的每一个都会有一些未跟踪的 A 位置文件(提示你通过后克隆钩子进入),告诉你的构建系统在哪里寻找它的 A 存储库。这具有工作的优势,但是您失去了跟踪 {B, C} 和 A 的并发版本的系统的便利性。同样,您可以使用通过钩子更新的 B 或 C 中的每个 B 或 C 中的 A 版本文件手动执行此操作,通过钩子读取,您可以完成这项工作,但我认为不可能使用 hg 中的 subrepos 实现。我的建议实际上归结为实施您自己的简化子回购系统。

于 2011-04-12T23:50:41.787 回答