版本控制中的项目结构

时间:2008-08-19 20:01:30

标签: svn version-control tfs branch project-structure

我知道在版本控制中至少有10种不同的方法来构建项目。我很好奇使用的方法是什么,哪些方法适合你。我曾与SVN,TFS以及目前/不幸的VSS合作过。我看到版本控制实现得非常糟糕而且还可以,但从来都不是很好。

为了让球滚动,这里是对我所看到的事情的回顾。

此示例基于SVN,但适用于大多数VCS(与分布式版本控制无关)。

  1. 分支属于网站的各个项目 /除法/网络/ PROJECTNAME / VB / SRC / [主干|分支|标签]

  2. 分支整个站点,在我看到的情况下,除了核心组件之外的整个站点都是分支的。 /分割/ [主干|分支|标签] /网络/ PROJECTNAME / VB / SRC /

  3. 使用main-line作为默认值,只有在巨大更改时才需要分支。

9 个答案:

答案 0 :(得分:10)

我们使用Java实现高度组件化的开发,我们在trunk中有大约250个具有独立生命周期的模块。依赖关系通过Maven进行管理(这是一种最佳实践),每次迭代(双周)积极开发的模块都会被标记为新版本。具有严格语义的3位数版本号(major.minor.build - 主要更改意味着向后兼容,轻微更改意味着向后兼容和构建数量更改意味着向后兼容)。我们的终极软件产品是一个集合,它可以作为Maven依赖项引入数十个单独的模块。

当我们需要为发布的版本进行错误修复或增强时,我们会分支模块/程序集,而我们无法提供HEAD版本。标记所有版本后,这很容易做到,但分支仍然会产生很大的管理开销(特别是保持分支与某些HEAD变更集同步),这部分是由我们的工具引起的,Subversion对于管理分支来说是次优的。

我们发现存储库中相当平坦且最重要的可预测树结构至关重要。它使我们能够构建发布工具,从手动发布过程中消除了许多痛苦和危险(更新的发行说明,项目编译,单元测试运行,标记生成,没有SNAPSHOT依赖项等)。避免在树结构中放置太多分类或其他逻辑。

我们粗略地执行以下操作:

svnrepo/
  trunk/
    modules/
      m1/ --> will result in jar file
      m2/
      ...
    assemblies/
      a1/
      ...
  tags/
    modules/
      m1/
        1.0.0/
        1.0.1/
        1.1.0/
       m2/
      ...
    assemblies/
      a1/
        iteration-55/
        ...
  branches/
    m1/
      1.0/
      ...

对于外部依赖项,我不能过分强调像Maven这样的东西:将依赖项作为对存储库中版本化,唯一标识的二进制工件的引用进行管理。

对于内部模块/项目结构:坚持标准。统一性是关键。同样,Maven可以在这里提供帮助,因为它决定了一个结构。许多结构都很好,只要你坚持下去。

答案 1 :(得分:7)

SVN示例:

躯干/

分支/

标记/

行李箱应保持在可以随时推动行李箱释放的位置。你应该知道没有巨大的漏洞(当然最终会有,但这是你应该努力的)。

每当您需要制作新功能时,请进行设计更改,无论如何,分支。在开始时标记该分支。然后当你完成分支标签时,它就在最后。这有助于合并回主干。

每次你需要推送一个版本,标签。这样,如果出现严重错误,您可以回滚到之前的版本。

此设置使主干保持尽可能干净,并允许您快速修复错误并将其推出,同时将大部分开发保留在分支机构中。

编辑:对于第三方的内容,它取决于。如果我可以避免它,我没有它在源代码管理下。我将它保存在源代码控制之外的目录中并从那里包含它。对于像jquery这样的东西,我确实将它置于源代码控制之下。原因是它简化了我的推送脚本。我可以简单地让它做一个svn导出和rsync。

答案 2 :(得分:6)

对于我的项目,我总是使用这种结构。

  
      
  • 躯干      
        
    • 配置
    •   
    • 文档
    •   
    • SQL      
          
      • 初始
      •   
      • 更新
      •   
    •   
    • SRC      
          
      • 应用
      •   
      • 测试
      •   
    •   
    • 第三方      
          
      • LIB
      •   
      • 工具
      •   
    •   
  •   
  • 标记
  •   
  • 分支
  •   
  • config - 用于存储我的应用程序配置模板。在构建过程中,我使用这些模板并使用实际值替换令牌占位符,具体取决于我正在构建的配置。
  • docs - 任何应用程序文档都放在这里。
  • sql - 我将我的sql脚本分成两个目录。一个用于初始数据库设置,用于初始化时,另一个位置用于基于数据库版本号运行的更新脚本。
  • src - 应用程序源文件。在这里,我根据应用程序和测试打破了源文件。
  • thirdparty - 这是我将我在应用程序中引用的第三方库放在GAC中不可用的地方。我基于lib和工具拆分它们。 lib目录包含需要包含在实际应用程序中的库。 tools目录包含我的应用程序引用的库,但仅用于运行单元测试和编译应用程序。

我的解决方案文件与我的构建文件一起放在trunk目录下。

答案 3 :(得分:2)

我可以理解不在存储库中放置二进制文件的逻辑,但我认为它也有很大的优势。如果你想能够从过去拉出特定的修订版(通常是较旧的标签),我希望能够拥有我需要的所有东西来自svn checkout。当然,这不包括Visual Studio或.NET框架,但拥有正确版本的nant,nunit,log4net等,这使得从结帐到构建变得非常容易。这种方式入门就像“svn co project”一样简单,然后是“nant build”。

我们做的一件事是将ThirdParty二进制文件放在一个单独的树中,并使用svn:external为它提供我们需要的版本。为了简化生活,我们将为每个已使用的版本提供一个文件夹。例如,我们可能会将ThirdParty / Castle / v1.0.3文件夹引入当前项目。这样,构建/测试产品的所有内容都需要在项目根目录内部或下方。根据我们的经验,磁盘空间的权衡非常值得。

答案 4 :(得分:2)

由于我们在同一棵树中拥有所有工件和构造,因此我们有类似的东西:

  • 中继线

    • 计划与;跟踪
    • 所需物品
    • 设计
    • 建筑
      • 数据库
      • 来源
  • 部署

  • QA
  • MA

答案 5 :(得分:2)

我更喜欢细粒度,非常有组织,自包含,结构化的存储库。有一个diagram说明了存储库维护过程的一般(理想)方法。例如,我的初始存储库结构(每个项目存储库应该具有)是:

/project
    /trunk
    /tags
        /builds
            /PA
            /A
            /B
        /releases
            /AR
            /BR
            /RC
            /ST
    /branches
        /experimental
        /maintenance
            /versions
            /platforms
        /releases

PA表示 pre-alpha A表示 alpha B表示 beta AR表示 alpha-release BR表示 beta-release RC表示发布候选人 ST表示稳定

builds 版本之间存在差异。

  • builds 文件夹下的标签的版本号对应于 N.x.K 模式,其中NK是整数。示例:1.x.05.x.110.x.33
  • releases 文件夹下的标签的版本号对应于 N.M.K 模式,其中NM和{{1是整数。示例:K1.0.05.3.1

最近,我开发了专门用于软件配置管理的培训,其中我描述了版本编号方法以及为什么这个存储库结构最好。以下是presentation slides

answer上还有关于'多个SVN存储库与单个公司存储库'的{​​{3}}。只要您在问题中解决存储库结构的这一方面,它可能会有所帮助。

答案 6 :(得分:1)

我认为团队采用的SCM政策和程序将非常依赖于他们正在使用的开发过程。如果你有一个50人的团队,有几个人同时处理重大变化,并且每6个月只发布一次,那么每个人都有自己的分支,他可以孤立地工作并且仅合并来自其他人,当他想要他们。另一方面,如果你是一个5人团队,所有人都坐在同一个房间里,那么分支的频率就更低了。

假设您正在一个小型团队工作,在这个团队中,沟通和协作很好并且发布频繁,那么分支IMO就没什么意义了。在一个项目中,我们只是将SVN版本号滚动到我们所有版本的产品版本号中,我们甚至从未标记过。在极少数情况下,在prod中发现了一个严重的错误,我们将直接从已发布的修订版中进行分支。但大部分时间我们只是修复了分支中的错误,并按计划在本周末从主干中释放。如果你的发布频繁,你几乎不会遇到一个不能等到下一次正式发布的bug。

我参与过其他项目,我们从来没有忘记过,但由于轻量级的开发过程和低级仪式,我们能够非常有效地使用轻量级版本控制策略。

我还要提到我写的所有内容都来自企业IT环境,其中只有一个给定代码库的生产实例。如果我正在处理部署在100个不同客户站点的产品,那么为了管理所有实例中的所有独立更新周期,分支和标记实践必须更加费力。

答案 7 :(得分:1)

  

外部依赖项如AJAXTookit或其他一些在多个项目中使用的第三方扩展呢?

源代码控制是针对源代码而非二进制文件。将任何第三方程序集/ jar放在单独的存储库中。如果你在Java世界工作,可以试试像Maven或Ivy这样的东西。对于.Net项目,只要您有关于其结构和更新方式的体面政策,简单的共享驱动器就可以正常运行。

答案 8 :(得分:0)

在切换到SVN之前,我们从一个巨大的存储库(超过4G)迁移到VSS的糟糕世界。我真的很挣扎如何为我们公司建立新的存储库。我们公司是非常“老”的学校。很难改变我是年轻的开发者之一,我才45岁!我是公司开发团队的一员,该团队为我们公司的许多部门工作。无论如何,我设置了像这样的目录

+ devroot
    +--Dept1
        +--Dept1Proj1
        +--Dept2Proj2
    +--Dept2
        +--Dept2Proj1
    +--Tools
        +--Purchase3rdPartyTools
        +--NLog
        +--CustomBuiltLibrary

我想要包括分支的能力,但老实说,此时此刻太多了。我们仍然在努力使用这个方案。

  • 如果您正在进行主要产品升级(即因为我们不进行分支),很难解决生产问题。
  • 很难管理从“Dev”到“Prod”的推广概念。 (甚至不要询问有关晋升到质量保证的问题)