首先,我知道这一点:您如何为内部软件项目组织Subversion存储库? 接下来,实际问题:我的团队正在重构我们的存储库,我正在寻找有关如何组织它的提示.(在这种情况下为SVN).这就是我们想出的.我们有一个存储库,多个项目和多个svn:externals交叉引用
\commonTools /*tools used in all projects. Referenced in each project with svn:externals*/ \NUnit.v2.4.8 \NCover.v.1.5.8 \\commonFiles /*settings strong name keys etc.*/ \ReSharper.settings \VisualStudio.settings \trash /*each member of the team has trash for samples, experiments etc*/ \user1 \user2 \projects \Solution1 /*Single actual project (Visual Studio Solution)*/ \trunk \src \Project1 /*Each sub-project resulting in single .dll or .exe*/ \Project2 \lib \tools \tests \Solution1.sln \tags \branches \Solution2 \trunk \src \Project3 /*Each sub-project resulting in single .dll or .exe*/ \Project1 /*Project1 from Solution1 references with svn:externals*/ \lib \tools \tests \Solution2.sln \tags \branches
清除词汇表:解决方案意味着单个产品,Project是Visual Studio项目(产生单个.dll或单个.exe)
这就是我们计划布置存储库的方式.主要问题是,我们有多个解决方案,但我们希望在解决方案之间共享项目.我们认为将这些共享项目移动到他们自己的解决方案中没有任何意义,相反,我们决定使用svn:externals在解决方案之间共享项目.我们还希望将常用的工具集和第三方库保存在存储库中的一个位置,并使用svn:externals在每个解决方案中引用它们.
您如何看待这种布局?特别是关于svn:externals的使用.这不是一个理想的解决方案,但考虑到所有的利弊,这是我们能想到的最好的解决方案.你会怎么做?
如果您按照我的建议(我有多年),您将能够:
- 将每个项目放在源代码管理中的任何位置,只要保留项目根目录中的结构
- 在任何机器上的任何位置构建每个项目,风险最小,准备工作量最小
- 只要您可以访问其二进制依赖项(本地"库"和"输出"目录),就可以完全构建每个项目
- 构建和使用任何项目组合,因为它们是独立的
- 构建和使用单个项目的多个副本/版本,因为它们是独立的
- 避免使用生成的文件或库混乱源控件存储库
我推荐(这是牛肉):
定义每个项目以生成单个主要可交付项,例如.DLL,.EXE或.JAR(默认使用Visual Studio).
将每个项目构造为具有单个根的目录树.
为其根目录中的每个项目创建一个自动构建脚本,该脚本将从头开始构建,并且不依赖于IDE(但如果可行的话,不要阻止它在IDE中构建).
考虑在Windows上使用nAnt for .NET项目,或基于您的操作系统,目标平台等的类似项目.
使每个项目构建脚本从单个本地共享"库"目录引用其外部(第三方)依赖项,每个此类二进制文件由版本:%DirLibraryRoot%\ComponentA-1.2.3.4.dll
,%DirLibraryRoot%\ComponentB-5.6.7.8.dll
.完全标识 .
使每个项目构建脚本将主要可交付成果发布到单个本地共享"输出"目录:%DirOutputRoot%\ProjectA-9.10.11.12.dll
,%DirOutputRoot%\ProjectB-13.14.15.16.exe
.
通过"库"和"输出"目录中的可配置和完全版本化的绝对路径(见上文),使每个项目构建脚本引用其依赖项,并且不在哪里.
永远不要让项目直接引用另一个项目或其任何内容 - 只允许引用"output"目录中的主要交付项(见上文).
通过可配置且完全版本化的绝对路径%DirToolRoot%\ToolA\1.2.3.4
,使每个项目构建脚本引用其所需的构建工具: ,%DirToolRoot%\ToolB\5.6.7.8
.
请以绝对相对于项目的根目录的路径中的每个项目生成脚本引用源内容: ${project.base.dir}/src
,${project.base.dir}/tst
(语法通过构建工具而异).
总是需要一个项目构建脚本来通过绝对可配置的路径引用每个文件或目录(根据可配置变量指定的目录):${project.base.dir}/some/dirs
或${env.Variable}/other/dir
.
绝不允许项目构建脚本使用相对路径引用ANYTHING,.\some\dirs\here
或者..\some\more\dirs
始终使用绝对路径.
永远不要让项目构建脚本使用没有可配置根目录的绝对路径来引用ANYTHING,例如C:\some\dirs\here
或\\server\share\more\stuff\there
.
对于项目构建脚本引用的每个可配置根目录,请定义将用于这些引用的环境变量.
尝试最小化配置每台计算机必须创建的环境变量的数量.
在每台机器上,创建一个shell脚本,该脚本定义必要的环境变量,这些变量特定于该机器(如果相关,可能特定于该用户).
不要将特定于机器的配置shell脚本放入源代码管理中; 相反,对于每个项目,将项目根目录中的脚本副本作为模板提交.
要求每个项目构建脚本检查其每个环境变量,如果未定义,则使用有意义的消息中止.
要求每个项目构建脚本检查其依赖的构建工具可执行文件,外部库文件和依赖项目可交付文件,并在这些文件不存在时中止有意义的消息.
抵制将任何生成的文件提交到源代码控制中的诱惑 - 没有项目可交付成果,没有生成的源,没有生成的文档等.
如果使用IDE,则生成可以使用的任何项目控制文件,并且不将它们提交到源代码控制(这包括Visual Studio项目文件).
使用所有外部库和工具的正式副本建立服务器,以便在开发人员工作站和构建计算机上进行复制/安装.备份它以及源代码控制存储库.
建立一个没有任何开发工具的持续集成服务器(构建机器).
考虑一个用于管理外部库和可交付成果的工具,例如Ivy(与Ant一起使用).
不要使用Maven - 它最初会让你开心,最终会让你哭泣.
请注意,这些都不是特定于Subversion的,并且大多数是针对任何操作系统,硬件,平台,语言等的项目的通用.我确实使用了一些操作系统和工具特定的语法,但仅用于说明 - - 我相信您会转换为您的操作系统或首选工具.
关于Visual Studio解决方案的附加说明:不要将它们放在源代码管理中!使用这种方法,您根本不需要它们,或者您可以生成它们(就像Visual Studio项目文件一样).但是,我发现最好将解决方案文件保留给各个开发人员,以便他们认为合适时创建/使用(但没有签入源代码控制).我Rob.sln
在工作站上保存了一个文件,我从中引用了我当前的项目.由于我的项目都是独立的,我可以随意添加/删除项目(这意味着没有基于项目的依赖项引用).
请不要使用Subversion外部(或其他工具中的类似),它们是反模式,因此是不必要的.
实现持续集成时,或者甚至只想自动执行发布过程时,请为其创建脚本.创建一个shell脚本:获取项目名称的参数(如存储库中列出的)和标记名称,在可配置的根目录中创建一个临时目录,检查给定项目名称和标记名称的来源(通过构造对于该临时目录,在Subversion的情况下适当的URL,执行运行测试并打包交付物的干净构建.此shell脚本应该适用于任何项目,并应作为"构建工具"项目的一部分检入源代码管理.您的持续集成服务器可以使用此脚本作为构建项目的基础,或者甚至可以提供它(但您仍可能需要自己的脚本).
@VonC:当你的构建脚本因为你在不知不觉中使用不兼容的Ant版本运行它而被烧毁后,你不想一直使用"ant.jar"而不是"ant-abcdjar".这在Ant 1.6.5和1.7.0之间尤为常见.概括,您总是想知道正在使用的每个组件的特定版本,包括您的平台(Java ABCD)和您的构建工具(Ant EFGH).否则,您最终会遇到一个错误,并且您的第一个大问题将是追踪您涉及的各种组件的版本.最好先解决这个问题.