【问题标题】:Adapting svn:externals usage for move to Mercurial调整 svn:externals 使用以迁移到 Mercurial
【发布时间】:2011-12-23 12:28:15
【问题描述】:

我们在公司环境中有一个 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 中分支主 repo 并为所有子存储库自动获取新分支吗?

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

【问题讨论】:

    标签: svn mercurial branch subrepos externals


    【解决方案1】:

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

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

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

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


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

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

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

    【讨论】:

    • 感谢这个非常有帮助和详细的回答。
    • +1 关于使用 Maven 等构建工具管理依赖项的部分。
    猜你喜欢
    • 1970-01-01
    • 2010-10-26
    • 1970-01-01
    • 2010-11-01
    • 1970-01-01
    • 1970-01-01
    • 2011-01-07
    • 2011-05-14
    • 2013-12-24
    相关资源
    最近更新 更多