版本控制中的项目结构
我知道在版本控制中至少有10种不同的方法来构造项目。我很好奇正在使用的某些方法以及哪种方法对我们有用。我曾经使用SVN,TFS和当前/不幸的是VSS。我已经看到版本控制的执行效果很差,虽然还可以,但是从来没有很好。
只是为了使事情顺利进行,这里是对我所见过的事情的回顾。
该示例基于SVN,但适用于大多数VCS(不适用于分布式版本控制)。
- 分支属于站点/ division / web / projectName / vb / src / [trunk | branches | tags]的各个项目
- 分支整个站点,就我所见的情况而言,除了核心组件之外,整个站点都是分支的。 / div // [trunk | branch | tags] / web / projectName / vb / src /
- 使用main-line作为默认选项,仅在必要时才进行巨大更改。
解决方案
回答
SVN示例:
树干/
分支/
标签/
行李箱应保持在可以随时从其推出释放物的位置。我们应该没有应该知道的巨大的bug(当然最终会出现,但这是我们应该努力的目标)。
每次我们需要制作新功能时,都可以进行设计更改(无论分支如何)。在开始时标记该分支。然后,在完成分支标记后,将其结尾。这有助于合并回主干。
每次需要发布时,请标记。这样,如果出现严重错误,则可以回滚到以前的版本。
此设置使主干尽可能保持干净,并允许我们进行快速的错误修复并将其推出,同时将大部分开发工作保留在分支机构中。
编辑:对于第三方的东西,这取决于。如果我可以避免它,那么我就不在源代码控制之下。我将其保存在源代码管理外部的目录中,并从那里包含它。对于诸如jquery之类的事情,我的确将其置于源代码控制之下。原因是它简化了我的推送脚本。我可以简单地让它执行svn导出和rsync。
回答
我认为团队采用的SCM政策和程序将非常依赖于他们正在使用的开发过程。如果我们有一个由50人组成的团队,同时有几个人同时从事主要变更,并且仅每6个月发布一次,那么每个人都有自己的分支机构可以独立工作,并且只能合并变更,这很有意义。其他人想要的时候。另一方面,如果我们是一个由5人组成的团队,他们都坐在同一个房间里,那么减少分支的频率就很有意义。
假设我们在一个小型团队中工作,该团队的沟通和协作良好,并且发布频繁,那么对分支IMO来说意义不大。在一个项目中,我们仅将SVN修订号滚动到所有发行版的产品版本号中,甚至从未标记过。万一在产品中发现一个严重的错误,我们将直接从发布的版本中分支出来。但是大多数时候,我们只是简单地修复了分支中的错误,并按计划在本周结束时从主干中释放了该错误。如果发布频率足够高,我们几乎永远不会遇到无法等到下一个正式版本的错误。
我参与了其他项目,但我们从来都无法避免,但是由于轻量级开发过程和低级的仪式,我们能够非常有效地使用轻量级版本控制策略。
我还要提到的是,我编写的所有内容都来自企业IT上下文,在该上下文中,给定代码库只有一个生产实例。如果我正在开发一种产品,该产品已在100个不同的客户站点上部署,则分支和标记实践必须更加费劲一些,以便管理所有实例之间的所有独立更新周期。
回答
What about external dependencies such a the AJAXTookit or some other 3rd party extension that's used on several projects?
源代码控制用于源代码,而不用于二进制文件。将所有第三方程序集/罐子保存在单独的存储库中。如果我们在Java世界中工作,请尝试使用Maven或者Ivy之类的工具。对于.Net项目,只要我们具有合理的结构和更新策略,一个简单的共享驱动器就可以很好地工作。
回答
对于我的项目,我总是使用这种结构。
trunk config docs sql initial updates src app test thirdparty lib tools tags branches
- config-用于存储我的应用程序配置模板。在构建过程中,我将使用这些模板,并根据要进行构建的配置将令牌占位符替换为实际值。
- docs-任何应用程序文档都放在这里。
- sql-我将sql脚本分为两个目录。一个用于我们刚开始时的初始数据库设置,另一个用于基于数据库版本号运行我的更新脚本的地方。
- src-应用程序源文件。在这里,我根据应用程序和测试中断源文件。
- 第三方-这是我将我引用的第三方库放在应用程序中的地方,而GAC中不提供这些库。我根据lib和工具将它们分开。 lib目录包含需要包含在实际应用程序中的库。 tools目录包含我的应用程序引用的库,但仅用于运行单元测试和编译应用程序。
我的解决方案文件与我的构建文件一起被放置在主干目录下。
回答
我们使用Java进行高度组件化的开发,在主干中有大约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 checkout获得所需的一切。当然,这不包括Visual Studio或者.NET框架,但是具有正确版本的nant,nunit,log4net等,使得从结帐到构建都非常容易。这种上手方式就像" svn co project"和" nant build"一样简单。
我们要做的一件事是将ThirdParty二进制文件放在单独的树中,并使用svn:external为其提供所需的版本。为了使生活更轻松,我们将为已使用的每个版本提供一个文件夹。例如,我们可以将ThirdParty / Castle / v1.0.3文件夹引入当前项目。这样,构建/测试产品所需的一切都在项目根目录之内或者之下。根据我们的经验,在磁盘空间上进行权衡非常值得。
回答
在切换到SVN之前,我们从拥有一个大型存储库(超过4G)的VSS的坏世界中迁移出来。我真的很难为我们的公司建立新的存储库。我们公司是非常"老"的学校。变革很难,我是年轻的开发人员之一,今年45岁!我是公司开发团队的成员,该团队负责公司多个部门的计划。无论如何,我这样设置目录
+ devroot
+--Dept1
+--Dept1Proj1
+--Dept2Proj2
+--Dept2
+--Dept2Proj1
+--Tools
+--Purchase3rdPartyTools
+--NLog
+--CustomBuiltLibrary
我想包括分支功能,但老实说,在这一点上太过分了。使用此方案,我们仍然遇到一些麻烦。
- 如果我们要进行主要产品升级,则很难解决生产问题(例如,因为我们不进行分支)
- 从" Dev"升级到" Prod"的概念很难管理。 (甚至不问有关晋升为质量检查的问题)
回答
由于我们将所有工件和构造都放在同一棵树中,因此我们具有以下内容:
- 要求
- 设计
- 数据库
- 解放
- 来源
- 部署
- 质量检查
- 嘛

