使用 SVN 中的设置 1),分支是一场噩梦,因为根据策略我总是必须分支public_code
,shared_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:externals
Subversion 以及它们如何映射到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
及其所有依赖项”,然后您可以在对测试满意时发布正式版本。这些“快照”构建无法精确复制,但这也不是必需的——只有最终版本需要严格和精确的依赖关系跟踪。