4

我们在公司环境中有一个 svn 存储库结构,如下所示:

root
  libs
    shared_lib1
    shared_lib2
    private_lib
  public_code
  private_code

其中 public_code 是一个外部存储库,它是开源的,来自公司外部的人具有读写访问权限。shared_lib1 和 shared_lib2 也是与来自其他公司的不同程序员组共享的外部存储库。我是维护者,基本上可以做任何技术上最好的事情,外部用户必须适应。

我现在想知道从这种结构转移到 mercurial 存储库的最佳方法是什么。

1)我可以使用 mercurial 子存​​储库密切模拟旧设置。或者
2) 我可以为我们创建一个大仓库,并为外部合作伙伴创建三个新的较小的独立存储库(基本上是分叉项目),并在大仓库和独立仓库之间交换变更集。

使用 svn 中的设置 1),分支是一场噩梦,因为根据策略,当我分支 root 时,我总是必须分支 public_code、shared_lib1 和 shared_lib2。为此,我必须四次调用 svn branch 并手动修改 svn:externals 属性三次。我可以轻松地在 mercurial 中分支主存储库并自动为所有子存储库获取新分支吗?

当我进行设置 2) 时,repos 之间的文件系统会有所不同。例如,我将在 repo“root”中有 public_code/Makefile,但该文件将只是 repo“public_code”中的“Makefile”。Mercurial 是否仍然能够在存储库之间同步更改?工作流程会是什么样子?

4

1 回答 1

5

使用 SVN 中的设置 1),分支是一场噩梦,因为根据策略我总是必须分支public_codeshared_lib1并且shared_lib2当我分支时root。为此,我必须调用svn branch四次并svn:externals手动修改属性三遍。我可以轻松地在 Mercurial 中分支主存储库并自动为所有子存储库获取新分支吗?

不,子存储库不是那样工作的。顶级存储库中的命名分支不会自动传播到子存储库。如果您1.x在代码中创建分支,则不清楚shared_lib1是否也应该有1.x分支。事实上,它可能不应该同时分支顶级代码分支,尤其是当该库被多个不同的顶级项目使用时。

当我进行设置 2) 时,repos 之间的文件系统会有所不同。例如,我将public_code/Makefile在 repo 中root,但文件将仅Makefile在 repo 中public_code。Mercurial 是否仍然能够在存储库之间同步更改?工作流程会是什么样子?

不,如果您这样创建存储库,则无法在存储库之间进行推送和拉取。当它们来自同一个“母亲”存储库时,您只能在存储库之间推/拉。听起来您将创建三个不相关的存储库。


在这种情况下,您应该仔细评估为什么要使用svn:externalsSubversion 以及它们如何映射到Mercurial 子存​​储库。它们不是svn:externals. 您还应该研究对子存储库的工具支持——包括 Mercurial 本身和您的 Mercurial 托管、您的持续构建系统等。我编写了部分 Mercurial 子存​​储库代码,并且从 Mercurial 2.0 开始,这里和那里仍然存在一些尖锐的边缘。

简而言之,子存储库给您的是子系统之间非常紧密的耦合。这通常是要避免的 :-) 我们努力使我们的软件系统松散耦合,因为这给了我们灵活性。

子存储库的主要用例是“构建存储库”,您可以在其中跟踪在给定构建中使用的组件的精确版本。您不能要求 Mercurial 跟踪子存储库中给定分支的提示,它始终会跟踪给定存储库中的给定变更集。这使得以后可以重新创建给定的签出成为可能:该.hgsubstate文件跟踪在每个子存储库中签出的精确变更集。

因此,如果您的root存储库不用于开发,而仅用于构建版本,那么子存储库实际上对您来说非常有用。工作流程将类似于

$ cd root
$ cd libs/shared_lib1
$ hg pull
$ hg update 2.0
$ cd ../..
$ make test && hg commit -m "Updated to sharedlib1 2.0"
$ hg tag 2.3

然后,您发布软件的 2.3 版,Mercurial 知道它依赖于shared_lib1. 当负责子组件的人员告诉您他们已经为您准备好新版本时,您会偶尔这样做。您的 CI 服务器当然可以每晚执行此操作,以查看组件是否协同工作!

如果开发人员root直接在其中工作并且如果他们对子组件进行更改作为他们在root. 这表明组件之间的耦合过于紧密:如果主代码依赖于子组件的确切变更集,那么子组件应该直接在主代码中。此外,hg commit在顶级存储库中,当ui.commitsubrepos=True. (默认值在 Mercurial 2.0 中更改为False。)这通常是不需要的,当它确实有意义时,那么子存储库将非常紧密地耦合,并且应该是顶级存储库的一部分。

因此,总结一下:如果root是“构建存储库”,请使用 subrepos。否则,您应该内联顶级存储库中的组件,或者您应该通过使用Maven或类似的东西来更松散地将各个部分耦合在一起来管理依赖项。这些工具通常会让您说“请使用最新版本root及其所有依赖项”,然后您可以在对测试满意时发布正式版本。这些“快照”构建无法精确复制,但这也不是必需的——只有最终版本需要严格和精确的依赖关系跟踪。

于 2011-12-26T16:43:03.007 回答