如何构建包含多个库和应用程序的存储库

hoc*_*chl 6 svn git version-control repository

我已经赢得了使用Git或Subversion重构/重新创建现有代码库的任务.在这种特殊情况下,存储库历史记录不一定重要.在分析了这种情况之后,我发现了一些确定好布局的问题.我已经阅读了很多博客和帖子,但我仍然不确定什么是最好的布局.

现有存储库包含一组包含文件,一组部分依赖于彼此的库,其中许多依赖于包含文件集.此外,还有两个依赖于库集的应用程序项目.此外,还有一组脚本可以使用其中一个应用程序和一些其他配置信息.我画了一个图表来澄清情况:

    +---------->include files
    |                ^
    |                |
library A -----> library B <----- library C <----- library D
  ^  ^                                |                ^
  |  |                                |                |
  |  +--------------------------------+                |
  |                                                    |
application 1        application 2 --------------------+
  ^
  |
script -----> configuration information
Run Code Online (Sandbox Code Playgroud)

目标是建立一个布局,其中每个组件可以尽可能独立地开发,并且具有一个发布(对于外部客户),其包含定义的标签版本的所有组件的集合,以便可以回溯到时间并为特定版本构建软件.

我想出了以下结构:

trunk/
  include/
  lib/
    library A/
    library B/
    library C/
    library D/
  app/
    application 1/
    application 2/
tags/
  1.0/
    include/
    lib/
      library A/
      library B/
      library C/
      library D/
    app/
      application 1/
      application 2/
  1.1/
    include/
    lib/
      library A/
      library B/
      library C/
      library D/
    app/
      application 1/
      application 2/
  ...
Run Code Online (Sandbox Code Playgroud)

每次我创建一个新版本时,我只需将整个存储库复制到标签中的新子目录.

这个解决方案的问题在于库本身没有单独的标记目录,并且我只希望有一个由标记组件组成的版本,并且此解决方案不会显示哪些组件在版本中具有哪些标记版本.我考虑使用单独的存储库,然后创建一个主存储库,其中包含一个发布子目录,其中我使用`svn:externals'和特定的tags子目录链接所有必需的组件,但不同的库和包含文件相互依赖,我不喜欢看看如何将代码划分为单独的实体.

有任何想法吗?

===============问题在28-1-2011继续===============

好的,我已经绘制了一个关于如何规划新布局的图表.目标是在一个存储库中链接各种依赖项的标记与svn:externals方法,例如我在//tags/projects/include/std /上设置trunk/projects/lib/library2/dependencies中的svn:externals 1.3.

trunk/
  projects/
    include/
      std/
    lib/
      library1/
        dependencies/
          std/ --> tags/projects/include/std/1.2
      library2/
        dependencies/
          std/ --> tags/projects/include/std/1.2
          library1/ --> tags/projects/lib/library1/1.4.3
      library3/
        dependencies/
          std/ --> tags/projects/include/std/1.3
          library1/ --> tags/projects/lib/library1/1.4
    app/
      application1/
        dependencies/
          library3/ --> tags/projects/lib/library3/1.1
      application2/
        dependencies/
          library1/ --> tags/projects/lib/library1/2.1
      application3/
        dependencies/
          std/ --> tags/projects/include/std/1.2
          library2/ --> tags/projects/lib/library2/1.5.2
    config/
      configuration1/
        dependencies/
          application1/ --> tags/projects/app/application1/2.3
      configuration2/
        dependencies/
          application1/ --> tags/projects/app/application1/1.6
      configuration2/
        dependencies/
          application2/ --> tags/projects/app/application1/1.6
tags/
  projects/
    include/
      std/
        1.2/
        1.3/
    lib/
      library1/
        1.4.3/
        1.4/
        2.1/
      library2/
        1.5.2/
      library3/
        1.1/
    app/
      application1/
        1.6/
        2.3/
branches/
  ...
Run Code Online (Sandbox Code Playgroud)

剩下的问题:

  • 这种设计是否可行,或者您是否看到任何重大缺陷?
  • 如果我将库复制到标签目录会发生什么?这也会复制svn:externals属性.这会导致问题,还是需要这种行为?
  • 我可以为所有外部指定一个明确的修订版,但标签不应该改变,所以目录不足以满足要求吗?
  • 将存储库拆分为开发存储库和使用svn:external的存储库是否是更好的解决方案?查看答案"用例"有什么好处"svn:externals"有什么好处?.

Upg*_*ave 6

我建议把分类法彻底改变.在颠覆中,我建议像这样的分类:

companyname/
  include/
    trunk/
    tags/
    branches/
  libraryA/
    trunk/
    tags/
    branches/
  libraryB/
    trunk/
    tags/
    branches/
  libraryC
    trunk/
    tags/
    branches/
  libraryD/
    trunk/
    tags/
    branches/
  application1
    trunk/
    tags/
    branches/
  application2
    trunk/
    tags/
    branches/
Run Code Online (Sandbox Code Playgroud)

在git中,我建议你应该为include,libraryA,libraryB,application1等创建一个单独的git repo ...

此结构允许您在不同部分之间创建任何类型的依赖关系(例如,application1中的分支可能依赖于libraryA项目的不稳定版本,而application1中的HEAD可能依赖于libraryA项目的稳定版本) .

这种结构也适用于大多数构建工具,如maven,rake,buildr,ant等.

您提供的分类法看起来对于部署的应用程序版本来说是一个很好的结构,但不是一个很好的版本控制结构.根据经验,如果您使用类似我建议的版本控制结构,我认为您会更好,然后使用构建脚本(或构建工具)来创建您在打包/部署/时所列出的结构运送你的应用程序

更新:详细说明工作周期可能会如何:

因此,例如,假设我们已经完成了对Application1的错误修复(让我们称之为1.0.0版本).最新和最大的更改将检入application1/trunk.此版本的Application1依赖于libraryD v0.5.0.您更新application1/trunk/README.txt,并注意此版本依赖于libraryD v0.5.0.或许,更重要的是,application/trunk中的构建脚本知道如何签出libraryD/tags/0.5.0.接下来,在application1/tags/1.0.0中创建一个标签(它只是当前状态下的trunk的副本).

现在,让我们说一周过去了,另一位开发人员将libraryD更新到版本1.3.0.您需要增强application1.因此,在application1/trunk中进行更改.然后更新application1/trunk/README.txt以表示您现在依赖于libraryD v1.3.0(同样,application1 v1.3.0的新构建脚本将检出libraryD/tags/1.3.0).将application1/trunk复制到application1/tags/1.1.0.

现在,如果需要,您可以随时恢复到application1/tags/1.0.0(并确信它将从libraryD/tags/0.5.0中提取代码.application/tags/1.1.0将使用libraryD 1.3.0版.

在subversion和git中,标记是指在给定时间点返回一组文件的引用.这意味着标签不会占用太多空间,因此我会提前和经常说标签;-)