我知道在版本控制中至少有10种不同的方法来构建项目。我很好奇使用的方法是什么,哪些方法适合你。我曾与SVN,TFS以及目前/不幸的VSS合作过。我看到版本控制实现得非常糟糕而且还可以,但从来都不是很好。
为了让球滚动,这里是对我所看到的事情的回顾。
此示例基于SVN,但适用于大多数VCS(与分布式版本控制无关)。
分支属于网站的各个项目 /除法/网络/ PROJECTNAME / VB / SRC / [主干|分支|标签]
分支整个站点,在我看到的情况下,除了核心组件之外的整个站点都是分支的。 /分割/ [主干|分支|标签] /网络/ PROJECTNAME / VB / SRC /
使用main-line作为默认值,只有在巨大更改时才需要分支。
答案 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
- 工具
- 标记
- 分支
我的解决方案文件与我的构建文件一起放在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)
由于我们在同一棵树中拥有所有工件和构造,因此我们有类似的东西:
中继线
部署
答案 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 和版本之间存在差异。
N.x.K
模式,其中N
和K
是整数。示例:1.x.0
,5.x.1
,10.x.33
N.M.K
模式,其中N
,M
和{{1是整数。示例:K
,1.0.0
,5.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
我想要包括分支的能力,但老实说,此时此刻太多了。我们仍然在努力使用这个方案。