你如何组织你的版本控制库?
首先,我知道这个: 你将如何为内部软件项目组织一个Subversion版本库? 接下来,真正的问题是:我的团队正在重组我们的存储库,我正在寻找如何组织它的提示。 (在这种情况下是SVN)。 这是我们想出来的。 我们有一个存储库,多个项目和多个svn:外部交叉引用
\commonTools /*tools used in all projects. Referenced in each project with svn:externals*/ \NUnit.v2.4.8 \NCover.v.1.5.8 \<other similar tools> \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
要清除词汇:解决scheme意味着单个产品,项目是一个Visual Studio项目(导致一个单一的.dll或单个.exe)
这就是我们计划如何布置存储库的方法。 主要问题是,我们有多个解决scheme,但我们希望在解决scheme中共享项目。 我们认为把这些共享项目移到他们自己的解决scheme上并没有什么意义,相反,我们决定使用svn:externals在解决scheme之间共享项目。 我们也希望将通用的工具和第三方库保存在版本库中的一个地方,然后用svn:externals在每个解决scheme中引用它们。
你觉得这个布局怎么样? 特别是关于使用svn:externals。 这不是一个理想的解决scheme,但考虑到所有的利弊,这是我们能想到的最好的。 你会怎么做?
如果你按照我的build议(我有多年),你将能够:
– 把每个项目放在源代码pipe理的任何地方,只要你把项目根目录下的结构保存下来
– 在任何机器上的任何地方build立每个项目,风险最小,准备最less
– 完全独立地构build每个项目,只要你能够访问它的二进制依赖项(本地“库”和“输出”目录)
– build立和使用任何项目组合,因为它们是独立的
– build立和使用单个项目的多个副本/版本,因为它们是独立的
– 避免使用生成的文件或库混淆源代码pipe理库
我推荐(这里是牛肉):
-
定义每个项目以生成单个主交付项,例如.DLL,.EXE或.JAR(Visual Studio默认)。
-
将每个项目组织为具有单个根的目录树。
-
为其根目录下的每个项目创build一个自动构build脚本,该脚本将从头开始构build,对IDE没有依赖关系(但是如果可行的话,不要阻止它在IDE中被构build)。
-
考虑Windows上.NET项目的nAnt,或基于您的操作系统,目标平台等类似的东西。
-
使每个项目构build脚本引用其外部(第三方)从一个本地共享“库”目录的依赖关系,每个这样的二进制完全由版本标识:
%DirLibraryRoot%\ComponentA-1.2.3.4.dll
,%DirLibraryRoot%\ComponentB-5.6.7.8.dll
。 -
使每个项目构build脚本将主要交付项发布到单个本地共享“输出”目录:
%DirOutputRoot%\ProjectA-9.10.11.12.dll
,%DirOutputRoot%\ProjectB-13.14.15.16.exe
。 -
通过在“库”和“输出”目录中的可configuration和完全版本化的绝对path(参见上文),使每个项目构build脚本引用其依赖关系,并且不另行通知。
-
切勿让项目直接引用另一个项目或其任何内容 – 只允许引用“输出”目录中的主要交付内容(见上文)。
-
%DirToolRoot%\ToolA\1.2.3.4
,%DirToolRoot%\ToolB\5.6.7.8
使每个项目的构build脚本通过可configuration的完全版本化的绝对path引用其所需的构build工具。 -
通过相对于项目根目录的绝对path使每个项目构build脚本引用源内容:
${project.base.dir}/src
,${project.base.dir}/tst
(语法因构build工具而异)。 -
总是需要一个项目构build脚本来通过一个绝对的,可configuration的path引用EVERY文件或目录(根源于一个可configurationvariables指定的目录):
${project.base.dir}/some/dirs
或${env.Variable}/other/dir
。 -
绝不允许项目构build脚本使用像
.\some\dirs\here
或..\some\more\dirs
这样的相对path引用ANYING,总是使用绝对path。 -
切勿让项目构build脚本使用没有可configuration根目录(如
C:\some\dirs\here
或\\server\share\more\stuff\there
的绝对path引用ANYING。 -
对于项目构build脚本引用的每个可configuration根目录,定义一个将用于这些引用的环境variables。
-
尝试最小化您为了configuration每台机器而必须创build的环境variables的数量。
-
在每台机器上,创build一个shell脚本来定义必要的环境variables,这是特定于该机器(可能特定于该用户,如果相关的话)。
-
不要把机器特定的configurationshell脚本放到源代码控制中; 相反,对于每个项目,将项目根目录中的脚本副本作为模板提交。
-
要求每个项目构build脚本检查其每个环境variables,如果没有定义,则使用有意义的消息中止。
-
要求每个项目构build脚本检查每个依赖的构build工具可执行文件,外部库文件和相关的项目可交付文件,如果这些文件不存在,则会放弃一个有意义的消息。
-
抵制将任何生成的文件提交到源代码控制的诱惑 – 没有项目交付成果,没有生成源文件,没有生成文档等。
-
如果您使用IDE,则可以生成任何项目控制文件,并且不要将其提交给源代码pipe理(这包括Visual Studio项目文件)。
-
使用所有外部库和工具的官方副本build立一个服务器,将其复制/安装在开发人员工作站上并构build机器。 备份它,连同你的源代码控制库。
-
build立一个不带任何开发工具的持续集成服务器(构build机器)。
-
考虑一个pipe理外部库和可交付成果的工具,比如Ivy(与Ant一起使用)。
-
不要使用Maven – 它最初会使你快乐,并最终让你哭泣。
请注意,这些都不是Subversion特有的,大部分对于针对任何操作系统,硬件,平台,语言等的项目都是通用的。我使用了一些操作系统和工具特定的语法,但仅用于说明 – – 我相信你会翻译成你的操作系统或select的工具。
有关Visual Studio解决scheme的其他说明:不要将它们放在源代码pipe理中! 使用这种方法,您根本不需要它们,或者可以生成它们(就像Visual Studio项目文件一样)。 但是,我发现最好将解决scheme文件留给个别开发人员,以便他们认为合适(但未签入到源代码pipe理)创build/使用。 我在我的工作站上保存一个Rob.sln
文件,从中引用我当前的项目。 由于我的项目都是独立的,我可以随意添加/删除项目(这意味着没有基于项目的依赖项引用)。
请不要使用Subversion外部(或其他工具类似),它们是反模式,因此是不必要的。
在实现持续集成时,或者甚至当您只想自动执行发布过程时,请为其创build一个脚本。 制作一个单一的shell脚本:采用项目名称参数(存储库中列出)和标签名称,在可configuration的根目录中创build一个临时目录,检查给定项目名称和标签名称的源代码(通过构build在Subversion的情况下适当的URL)到这个临时目录,执行一个干净的构build,运行testing并打包可交付成果。 这个shell脚本应该在任何项目上工作,并且应该作为“构build工具”项目的一部分被检入到源代码控制中。 你的持续集成服务器可以使用这个脚本作为构build项目的基础,或者甚至可以提供它(但你仍然可能需要你自己的)。
@VonC:当你的构build脚本崩溃时,你不想在任何时候都用“ant.jar”而不是“ant-abcdjar”工作,因为你不知不觉地用Ant的不兼容版本运行它。 这在Ant 1.6.5和1.7.0之间特别常见。 一般来说,你总是想知道每个组件的特定版本正在被使用,包括你的平台(Java ABCD)和你的构build工具(Ant EFGH)。 否则,您将最终遇到一个错误,您的第一个BIG问题将会跟踪您所涉及的各个组件的版本。 预先解决这个问题只是更好。
我相信使用Subversion的实用版本控制拥有组织仓库所需的一切。
我们已经设置了几乎完全符合您发布的内容。 我们使用一般forms:
\Project1 \Development (for active dev - what you've called "Trunk", containing everything about a project) \Branches (For older, still-evolving supported branches of the code) \Version1 \Version1.1 \Version2 \Documentation (For any accompanying documents that aren't version-specific
虽然我认为不如你的例子那么完整,但它对我们来说很好,让我们保持独立。 我喜欢每个用户都有一个“Thrash”文件夹的想法 – 目前,这些types的项目并没有在Source控制中结束,我一直认为他们应该这样做。
我认为所提出的结构的主要缺点是共享项目只能通过添加第一个解决scheme来进行版本控制(除非svn:externals比我想像中的更有趣)。 例如,当您为Solution2的第一个版本创build一个分支时,Project1将不会被分支,因为它位于Solution1中。 如果您需要稍后从该分支生成(QFE版本),则在分支时将使用最新版本的Project1而不是Project1的版本。
出于这个原因,将共享项目放在一个或多个共享解决scheme中(从而在您的结构中放置顶层目录),然后在每次发布任何解决scheme时都可以将它们分支。
为什么在一个存储库中全部存储? 为什么不为每个项目设置单独的存储库(我的意思是“解决scheme”)?
那么,至less我已经习惯了每个存储库一个项目的方法。 您的存储库结构似乎过于复杂。
你打算把多less个项目放进这个大型的仓库? 2? 3? 10? 100?
当你取消一个项目的开发时,你会做什么? 只要将其从存储库树中删除,以便将来很难find。 或者让它躺在永远? 或者当你想把一个项目完全移到另一个服务器上?
那么所有这些版本号的混乱呢? 一个项目的版本号为2,10,11,而另一个项目的版本号为1,3,4,5,6,7,8,9,12 …
也许我很愚蠢,但是我喜欢每个存储库一个项目。
要添加到相对path问题:
我不确定这是一个问题:
只需在名为“Solution1”的目录下签出Solution1 / trunk,解决scheme2:实际上代表分支的目录的目标是一旦导入到工作区中就不可见 。 因此在'Solution1'(实际上是'Solution1 / trunk')和'Solution2'(Solution2 / trunk)之间可以有相对path。
RE:相对path和共享文件问题 –
看来这是svn具体的,但这不是一个问题。 另一个人已经提到了单独的存储库,这可能是我可以想到的最好的解决scheme,如果你有不同的项目涉及任意其他项目。 在没有共享文件的情况下,OP解决scheme(以及许多其他的)将正常工作。
我们仍在努力解决这个问题,而且我有3个不同的努力(不同的客户),我必须立即解决这个问题,因为我接手设置了不存在或者不好的版本控制。
我有一个类似的布局,但我的树干,树枝,一路标签在顶部。 所以:/ trunk / main,/ trunk / utils,/ branches / release /等
当我们想要尝试其他的版本控制系统时,这真的很方便,因为许多翻译工具在基本的教科书SVN布局上效果最好。