我知道在版本控制中至少有10种不同的方法来构建项目.我很好奇使用的方法是什么,哪些方法适合你.我曾与SVN,TFS以及目前/不幸的VSS合作过.我已经看到版本控制实现得非常糟糕而且很好,但从来都不是很好.
为了让球滚动,这里是对我所看到的事情的回顾.
此示例基于SVN,但适用于大多数VCS(与分布式版本控制无关).
分支作为site/division/web/projectName/vb/src/[trunk | branches | tags]一部分的各个项目
分支整个站点,在我看到的情况下,整个站点除了核心组件是分支的./部门/ [车厢|分支机构|标签] /网站/项目名称/ VB/src目录/
使用main-line作为默认值,仅在必要时进行分支以进行大量更改.
Boris Terzic.. 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可以在这里提供帮助,因为它决定了一个结构.许多结构都很好,只要你坚持下去.
我们使用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可以在这里提供帮助,因为它决定了一个结构.许多结构都很好,只要你坚持下去.
SVN示例:
树干/
科/
标签/
行李箱应保持在可以始终从中释放的位置.你应该知道没有巨大的漏洞(当然最终会有,但这是你应该努力的).
每当你需要制作一个新功能时,做一个设计更改,无论如何,分支.在开始时标记该分支.然后当你完成分支标签时,它就在最后.这有助于合并回主干.
每次你需要推送一个版本,标签.这样一来,如果出现严重错误,您可以回滚到之前的版本.
此设置使主干保持尽可能干净,并允许您快速修复错误并将其推出,同时将大部分开发保留在分支机构中.
编辑:对于第三方的东西,它取决于.如果我可以避免它,我没有它在源代码管理下.我将它保存在源代码控制之外的目录中并从那里包含它.对于像jquery这样的东西,我确实将它置于源代码控制之下.原因是它简化了我的推送脚本.我可以简单地让它做一个svn导出和rsync.
对于我的项目,我总是使用这种结构.
树干
配置
文档
SQL
初始
更新
SRC
应用
测试
第三方
LIB
工具
标签
分支机构
config - 用于存储我的应用程序配置模板.在构建过程中,我使用这些模板并使用实际值替换令牌占位符,具体取决于我正在构建的配置.
docs - 任何应用程序文档都放在这里.
sql - 我将我的sql脚本分成两个目录.一个用于初始数据库设置,用于初始化时,另一个用于基于数据库版本号运行的更新脚本.
src - 应用程序源文件.在这里,我根据应用程序和测试打破源文件.
第三方 - 这是我在我的应用程序中引用我的第三方库而在GAC中不可用的地方.我基于lib和工具拆分它们.lib目录包含需要包含在实际应用程序中的库.tools目录包含我的应用程序引用的库,但仅用于运行单元测试和编译应用程序.
我的解决方案文件与我的构建文件一起放在trunk目录下.