调整svn:externals用法以移动到Mercurial

时间:2011-12-23 12:28:15

标签: svn mercurial branch subrepos externals

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

root
  libs
    shared_lib1
    shared_lib2
    private_lib
  public_code
  private_code

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

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

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

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

当我进行设置2)时,repos之间的文件系统会有所不同。例如。我将在repo“root”中使用public_code / Makefile,但该文件将只是repo“public_code”中的“Makefile”。 Mercurial仍然能够同步回购之间的变化吗?工作流程怎么样?

1 个答案:

答案 0 :(得分:5)

  

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

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

  

当我进行设置2)时,repos之间的文件系统会有所不同。例如。我将在回复public_code/Makefile中使用root,但该文件在回购Makefile中仅为public_code。 Mercurial仍然能够同步回购之间的变化吗?工作流程怎么样?

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


在这种情况下,您应该仔细评估为什么您在Subversion中有svn:externals以及它们如何映射到Mercurial subrepositories。它们不是svn:externals的1-1替代品。您还应该查看subrepos的工具支持 - 包括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的2.0版本。当负责子组件的人员告诉您他们已为您准备好新版本时,您会偶尔执行此操作。您的CI服务器当然可以每晚进行此操作以查看组件是否协同工作!

如果开发人员直接在root工作,并且他们在root中作为其工作的一部分对子组件进行了更改,则子存储库的工作效果不佳。这表明组件之间的耦合过于紧密:如果主代码依赖于子组件的精确变更集,那么子组件应该直接在主代码中。此外,顶级存储库中的hg commit将在ui.commitsubrepos=True时递归并在子页面中使用相同的提交消息。 (Mercurial 2.0中的默认值已更改为False。)这通常是不可取的,当它确实有意义时,那么subrepo非常紧密耦合,应该是顶级仓库的一部分。

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