代码之家  ›  专栏  ›  技术社区  ›  Mr. Boy

在SVN中构建大型多应用代码库的正确方法是什么?

  •  1
  • Mr. Boy  · 技术社区  · 14 年前

    我们现在有一个带有代码的回购, http://John.svn.cvsdude.com ,单个SVN项目 http://John.svn.cvsdude.com/MyProject ,它包含用于个别Visual C++解决方案的几个子目录。

    这一切都是从一个应用程序开始的,尽管我们分离了单独的库项目以供将来重用,但它仍然是同一个SVN项目。假设我们的目标是让多个应用程序在使用的库中有一些重叠,那么在SVN中设置这一点的正确/最佳方法是什么?当然,人们可以只保留一个SVN项目,并将应用程序项目和库项目作为子目录,但这似乎不太正确。

    假设我们有app1、app2、app3和librarya、libraryb、libraryc、libraryd,这些都是单独的项目/解决方案…您将如何在一个(或多个回购协议)下组织这项交易?是否有最佳实践?

    3 回复  |  直到 14 年前
        1
  •  2
  •   Grzegorz Gierlik    14 年前

    我愿意 保持一切 在里面 一个仓库 把每个项目 图书馆 在存储库的单独根目录中(请参见 Planning Your Repository Organization 详情请参阅。

    记住存储库结构 不必 与磁盘上的项目文件结构相同。

    我也会 使用 svn-externals 在不同的项目之间共享库目录(作为存储库的单独根文件夹保存)。

        2
  •  2
  •   jackr    14 年前

    我是来自协作云服务公司的杰克。首先,感谢您成为一个编码客户!

    你用“项目”来描述你的情况,但这是一个模棱两可的术语,颠覆本身根本没有任何概念。这里真正要考虑的不是颠覆本身,而是您的构建工具和发布策略。您想要的配置最能支持您想要做的事情。

    例如,所有这些应用程序和库是否同时发布?完全独立?有些混合?这个答案可能会改变吗?

    如果它们都是一次性发布的,那么尽可能容易地识别每个应用程序的哪个版本与其他应用程序的哪个版本一起发布就有重要的价值。通过这种方式,可以验证错误报告,实现修复,并以一致、一致的方式合并补丁。为了达到这个目的,我会 使用一些人建议的/app/主干、标签、分支结构,但要遵循规范

    /trunk/app1
    /trunk/app2
    /tags/TAGNAME/app1
    /tags/TAGNAME/app2
    /branches/BRANCHNAME/app1
    /branches/BRANCHNAME/app2
    

    结构。这允许您在一个命令中对整个树、所有应用程序和库进行分支、标记和合并:

    svn cp URL/trunk URL/tags/TAGNAME
    

    另一方面,如果这些东西是独立的,那么你最好

    /app1/trunk
    /app1/tags
    /app1/branches
    /app2/trunk
    /app2/tags
    /app2/branches
    ...
    

    例如,通过这种方式标记一个应用不会影响另一个应用。

    在混合的情况下,您仍然可以实现协调的分支(如果合适的话),但是您必须在工作副本中使用分支,或者稀疏签出(如果工作副本很大)。或者,您可以标记或分支整个存储库,即使标记或分支对大多数存储库没有意义:Subversion标记和分支存储起来很便宜,而且(如果您使用URL到URL形式的“svn cp”)制作起来也很便宜;不将事物标记为不相关的标记的唯一原因是,它会混淆人类。但这是一个很强的原因,所以混合模型最好用“app/trunk”结构处理,以避免混淆。

    您可以在Apache基金会存储库中找到“/APP/Bar”方法的好例子。所有Apache项目(包括Subversion本身)都存储在一个Subversion存储库中。那里有大约100个项目,尽管有一些相互依赖关系,但它们几乎都是独立管理的。你可以浏览这个巨大的回购(可能是公共世界上最大的单一颠覆性回购),从 root of all ASF projects . 在实践中有一些多样性,但一个很好的例子是 Subversion itself .

    同样值得注意的是:就颠覆而言,你总是可以改变这些东西。“标签”和“分支”实际上只是复制品;你可以随意地在你喜欢的时候重新排列东西。但也有一些警告:

    • 它会迷惑人类
    • “树冲突”(添加、删除、移动或重命名文件或目录)可能会使以后的合并很痛苦。合并工具的功能是保存您的工作。所有的合并工具最终,为了一个足够困难的合并,把决策推回到人类身上;重要的问题是,没有这个,他们能得到多少正确的结果。树形冲突导致当前的颠覆(1.6或更好)比你想的更频繁地进行。因此,最好不要过于频繁地重新排列顶级目录,并准备好干预和清理任何跨越此类重新排列的合并。
        3
  •  0
  •   Daniel Lidström    14 年前

    我建议在同一个存储库中使用以下布局:

    App1\
        trunk
        tags
        branches
    App2\
        trunk
        tags
        branches
    App3\
        trunk
        tags
        branches
    LibraryA\
        trunk
        tags
        branches
    LibraryB\
        trunk
        tags
        branches
    LibraryC\
        trunk
        tags
        branches
    LibraryD\
        trunk
        tags
        branches
    

    现在,我对您的发布时间表做了一些假设。我假设每个应用程序和库是在不同的计划下发布的。实际上,这是一个最坏的情况,但我的计划允许这样做。每个应用程序都需要预先编译其依赖项,并将其包含在存储库的目录中。鉴于App1依赖于库B和库C,它的外观如下:

    App1\
        trunk\
            deps\
                LibraryB, release 1.1
                LibraryC, release 4.3
        tags
        branches
    

    这意味着,每当您对主干进行分支时,都会得到必要的库,这大大简化了事情。请注意,它是库的已编译二进制文件,而不是它们的源文件。

    主干的一个分支将使用上述版本,由于不允许修改它们,所以任何错误修复都需要进入App1。同时,要使用libb&c的新版本,当库团队发布它们时,您可以在主干中更新它们的版本。因此,一段时间后,您的存储库可能如下所示:

    App1\
         trunk\
             deps\
                 LibraryB, release 1.3
                 LibraryC, release 4.4
         tags\
             release-1.0\
                 deps\
                     LibraryB, release 1.1
                     LibraryC, release 4.3
         branches\
             stable-2.0\
                 deps\
                     LibraryB, release 1.2
                     LibraryC, release 4.2
    

    主干中的工作允许使用最新的库版本。版本1.0使用的是固定版本(这里是最早的版本),而稳定分支使用的是以前版本的库。

    上面的计划是我在上一个雇主那里想了很多,但却一直没有付诸实施。要使其工作,您需要将代码库拆分为应用程序/库,并且开发可以并行进行。我们不是这样的。但我坚信这是一个值得一试的目标。

    祝你好运!

    另外,我强烈推荐 反对 外部的。他们可以使分支机构管理更加困难。例如,如果一个外部变更和一个分支依赖于它,那么您就有可能把这个分支弄乱(例如使它不可编译)。