Hg子存储库依赖项

Tom*_*ver 19 mercurial dependencies subrepos

过去(这里这里)有关于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版本必须始终使用与A引用的版本相同的A版本.给定版本的D(否则它将在运行时崩溃).我真正想要的是允许他们在同一目录中作为兄弟姐妹互相引用 - 即D's .hgsub看起来像下面这样,而B和C看起来就像是第一行.

..\A = https:(central kiln repo)\A
..\B = https:(central kiln repo)\B
..\C = https:(central kiln repo)\C
Run Code Online (Sandbox Code Playgroud)

然而,这似乎不起作用:我可以看到为什么(给人们足够的绳索让自己挂起来很容易),但我觉得它是我的依赖关系的最佳解决方案,这是一种耻辱.我已经阅读了一些建议的解决方案,我会快速概述这些解决方案以及它们为什么不能为我工作:

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

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

    这种方法的问题:

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

    A = ..\A
    
    Run Code Online (Sandbox Code Playgroud)

    这种方法的问题:

    • 我仍然在磁盘上有三个副本
    • 第一次克隆B或C时,它将尝试递归地从"..\A"中提取A的引用版本,这可能不存在,可能会导致错误.如果它不存在,则不知道应该找到回购的位置.
    • 当我进行递归推送更改时,D\B\A中的更改不会进入共享的中央存储库; 他们只是被推到D\A而不是.因此,如果我连续两次推送,我可以保证所有更改都会正确传播,但这是一个相当的软糖.
    • 类似地,如果我做(手动)递归拉动,我必须得到正确的顺序以获得最新的更改(即在我拉D\B\A之前拉D\A)
  3. 使用符号链接将文件夹\ D\B\A指向D\A等.

    这种方法的问题:

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

这些是最好的解决方案吗?我的初始.hgsub(见上)是一个梦想有没有一个很好的理由,还是有办法我可以请求/实现这个改变?

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

Tom*_*ard 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的项目功能子模块的最佳实践中稍有不同


hca*_*ver 2

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

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

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