您如何组织版本控制存储库?

2023-11-23

首先,我知道这一点:您将如何为内部软件项目组织 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
   \<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

为了澄清词汇:解决方案意味着单一产品,项目是一个 Visual Studio 项目(生成单个 .dll 或单个 .exe)

这就是我们计划布置存储库的方式。主要问题是,我们有多个解决方案,但我们希望在解决方案之间共享项目。 我们认为将这些共享项目移动到它们自己的解决方案中实际上没有任何意义,因此我们决定使用 svn:externals 在解决方案之间共享项目。我们还希望将一组通用工具和第三方库保留在存储库中的一个位置,并在每个解决方案中使用 svn:externals 引用它们。

你觉得这个布局怎么样?特别是关于 svn:externals 的使用。这不是一个理想的解决方案,但考虑到所有优点和缺点,这是我们能想到的最好的解决方案。你会怎么做?


如果您遵循我下面的建议(我多年来一直这样做),您将能够:

-- 将每个项目放在源代码管理中的任何位置,只要保留项目根目录下的结构即可

-- 以最小的风险和最少的准备在任何地方、任何机器上构建每个项目

-- 完全独立地构建每个项目,只要您有权访问其二进制依赖项(本地“库”和“输出”目录)

-- 构建和使用任意项目组合,因为它们是独立的

-- 构建并使用单个项目的多个副本/版本,因为它们是独立的

-- 避免生成的文件或库弄乱源代码控制存储库

我推荐(这是牛肉):

  1. 定义每个项目以生成单个主要可交付成果,例如 .DLL、.EXE 或 .JAR(Visual Studio 的默认设置)。

  2. 将每个项目构建为具有单个根的目录树。

  3. 为根目录中的每个项目创建一个自动构建脚本,该脚本将从头开始构建它,不依赖于 IDE(但如果可行,不要阻止它在 IDE 中构建)。

  4. 考虑将 nAnt 用于 Windows 上的 .NET 项目,或基于您的操作系统、目标平台等的类似项目。

  5. 使每个项目构建脚本从单个本地共享“库”目录引用其外部(第 3 方)依赖项,每个此类二进制文件均由版本完全标识:%DirLibraryRoot%\ComponentA-1.2.3.4.dll, %DirLibraryRoot%\ComponentB-5.6.7.8.dll.

  6. 使每个项目构建脚本将主要可交付成果发布到单个本地共享“输出”目录:%DirOutputRoot%\ProjectA-9.10.11.12.dll, %DirOutputRoot%\ProjectB-13.14.15.16.exe.

  7. 使每个项目构建脚本通过“库”和“输出”目录中的可配置且完全版本化的绝对路径(见上文)引用其依赖项,而不是其他地方。

  8. 永远不要让一个项目直接引用另一个项目或其任何内容——只允许引用“输出”目录中的主要可交付成果(见上文)。

  9. 使每个项目构建脚本通过可配置且完全版本化的绝对路径引用其所需的构建工具:%DirToolRoot%\ToolA\1.2.3.4, %DirToolRoot%\ToolB\5.6.7.8.

  10. 让每个项目构建脚本通过相对于项目根目录的绝对路径引用源内容:${project.base.dir}/src, ${project.base.dir}/tst(语法因构建工具而异)。

  11. 始终需要项目构建脚本通过绝对的可配置路径引用每个文件或目录(以可配置变量指定的目录为根):${project.base.dir}/some/dirs or ${env.Variable}/other/dir.

  12. 永远不要允许项目构建脚本引用任何具有相对路径的内容,例如.\some\dirs\here or ..\some\more\dirs,始终使用绝对路径。

  13. 切勿允许项目构建脚本使用没有可配置根目录的绝对路径引用任何内容,例如C:\some\dirs\here or \\server\share\more\stuff\there.

  14. 对于项目构建脚本引用的每个可配置根目录,定义将用于这些引用的环境变量。

  15. 尝试最大程度地减少配置每台计算机时必须创建的环境变量的数量。

  16. 在每台计算机上,创建一个定义必要的环境变量的 shell 脚本,该环境变量特定于该计算机(并且可能特定于该用户,如果相关)。

  17. 不要将特定于机器的配置 shell 脚本放入源代码管理中;相反,对于每个项目,在项目根目录中提交脚本的副本作为模板。

  18. 要求每个项目构建脚本检查其每个环境变量,如果未定义,则中止并显示有意义的消息。

  19. 要求每个项目构建脚本检查其每个依赖的构建工具可执行文件、外部库文件和依赖的项目可交付文件,如果这些文件不存在,则中止并显示有意义的消息。

  20. 抵制将任何生成的文件提交到源代码管理的诱惑——没有项目可交付成果、没有生成的源代码、没有生成的文档等。

  21. 如果您使用 IDE,请尽可能生成项目控制文件,并且不要将它们提交到源代码管理(这包括 Visual Studio 项目文件)。

  22. 建立一个服务器,其中包含所有外部库和工具的正式副本,以便在开发人员工作站和构建机器上复制/安装。备份它以及您的源代码控制存储库。

  23. 建立一个没有任何开发工具的持续集成服务器(构建机器)。

  24. 考虑使用一个工具来管理外部库和可交付成果,例如 Ivy(与 Ant 一起使用)。

  25. 不要使用 Maven——它一开始会让你高兴,最终会让你哭泣。

请注意,这些都不是 Subversion 特有的,而且大多数都是针对任何操作系统、硬件、平台、语言等的项目所通用的。我确实使用了一些特定于操作系统和工具的语法,但仅用于说明- -我相信您会翻译成您选择的操作系统或工具。

关于 Visual Studio 解决方案的附加说明:不要将它们置于源代码管理中!使用这种方法,您根本不需要它们,或者您可以生成它们(就像 Visual Studio 项目文件一样)。但是,我发现最好将解决方案文件留给各个开发人员根据他们认为合适的方式创建/使用(但不签入源代码管理)。我保留一个Rob.sln我的工作站上的文件,我从中引用了当前的项目。由于我的项目都是独立的,因此我可以随意添加/删除项目(这意味着没有基于项目的依赖项引用)。

请不要使用 Subversion 外部组件(或其他工具中的类似组件),它们是反模式,因此没有必要。

当您实施持续集成时,甚至当您只想自动化发布过程时,请为其创建一个脚本。制作一个 shell 脚本:获取项目名称(如存储库中列出的)和标签名称的参数,在可配置的根目录中创建临时目录,检查给定项目名称和标签名称的源(通过构造适当的 URL(如果是 Subversion)到该临时目录,执行干净的构建,运行测试并打包可交付成果。该 shell 脚本应该适用于任何项目,并且应该作为“构建工具”项目的一部分签入源代码管理。您的持续集成服务器可以使用此脚本作为构建项目的基础,或者它甚至可能提供它(但您仍然可能需要自己的脚本)。

@VonC:当你的构建脚本中断时,你不想一直使用“ant.jar”而不是“ant-a.b.c.d.jar”,因为你在不知不觉中使用不兼容版本的Ant运行它。这在 Ant 1.6.5 和 1.7.0 之间尤其常见。概括而言,您总是想知道正在使用的每个组件的具体版本,包括您的平台 (Java A.B.C.D) 和构建工具 (Ant E.F.G.H)。否则,您最终会遇到错误,而您的第一个大问题将是跟踪所涉及的各个组件的版本。最好提前解决这个问题。

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

您如何组织版本控制存储库? 的相关文章

  • pom.xml 中的 Maven 标记

    默认情况下 Maven 将所有依赖项下载到 user home m2 repository 目录 我读到了 LocalRepository 标签 它允许我们更改默认路径 我尝试添加此标签在 pom xml 文件中添加不同位置 但我在 pom
  • Windows XP 上无法打开存储库错误

    我正在尝试提交到我的本地 SVN 它一直工作得很好 但今天它给出了这个错误 Unable to open repository file C wamp www svns myproject dir subdir 可能是什么问题呢 编辑 完整
  • 使用 svn_access_file 中的 LDAP 组设置 Subversion 存储库

    如果我从头开始这样做 我会创建这两个单独的存储库 不幸的是 我不得不凑合着用现有的东西 我们的存储库如下所示 trunk tags branches secret trunk secret tags secret branches 我的 S
  • Delphi TImageList 位图更改

    我正在使用 Delphi XE2 Update 3 Update 4 与我们的一些第 3 方组件不兼容 因此我们尚未更新 我在我的应用程序中使用 TImageList 我注意到很多时候当它从源视图切换到表单视图 F12 时 突然之前未修改的
  • Access 2007 数据库和应用程序的版本控制

    我需要对 Microsoft Access 2007 数据库和应用程序进行版本控制 目前 所有内容都包含在单个 mdb 文件中 该应用程序包括 Forms VBA code 实际数据库 我假设我需要将数据库与表单 代码分开 我希望能够将表单
  • 如何将 git 存储库中的现有目录设为 git 子模块

    我对 git submodules 很困惑 基本上我的问题是我无法让 git 理解这一点 main project submodule是一个子模块 我对 git 子模块有很好的经验 in my 点文件存储库 https github com
  • git:切换分支而不分离头

    我在 github 上有一个存储库 其中有一个主分支 master 和一个用于一些实验工作的分支 我做了一些提交并推送到实验分支 一切都很好 现在 在另一台机器上 我尝试克隆我的存储库 git clone存储库 然后切换到实验分支 git
  • 如何跳过 Maven 存储库中的发布或特定模块

    Heyho 我有一个具有以下结构的 Maven 项目 parent 项目清单 API模块 module2 module5 test 分配 组装 所以首先我运行父模块 然后运行构建 api 的模块 然后运行依赖于 api 的模块 然后运行一个
  • 在 Ubuntu 12.04 上的 Apache 上配置 SVN 服务器

    我正在尝试通过 HTTP 访问现有的 Subversion 服务器 我的dav svn conf文件看起来像
  • Git推送大文件时远端意外挂断

    当我尝试推送到我的 bitbucket 存储库时 出现以下错误 事实上 在 GitHub 中也是如此 数物体 48 完成 增量压缩最多使用 2 个线程 压缩对象 100 38 38 完成 写入对象 100 48 48 1 95 MiB 38
  • Github 拉取请求显示太多更改/提交

    我们有两个分行 develop and master 由于某种原因 当我创建 PR 时develop gt master 它显示了以前提交和更改的完整列表 即使我只做了一行更改develop 另外 当我能够从命令行合并时 它会说 无法自动合
  • 尽管有 svn 复制,如何 git svn 克隆完整历史记录

    在我的公司 我们即将从 svn 切换到 git 我们使用的 SVN 非常大 没有 svn 布局 并且在每个版本拆分上我们都制作了一个 svn 副本 SVN存储库结构 svnserver company de product xy 主要版本号
  • 如何使用 ClearCase 执行递归结帐?

    我想查看指定文件夹的所有子目录中的所有文件 使用 GUI 来执行此操作很痛苦 因为没有递归结帐选项 请注意 ClearCase 以文件为中心 而不是以存储库为中心 如 SVN 或 CVS 这意味着签出所有文件很少是一个好的解决方案 并且使用
  • 在 Web 应用程序中显示最新的提交值?

    我有一些 Rails 应用程序 我使用 Git 作为版本控制系统 我使用 GitHub 或 Beanstalk 作为存储库主机 从理论上讲 我想要做的事情非常简单 以某种方式在 Web 应用程序的页脚中显示最新的提交 ID 号 哈希值 这样
  • svn propget svn:忽略。什么也没返回,但 svn 显然忽略了我的文件

    我正在尝试将现有的 iPhone 项目添加到 unfuddle com 上的 subversion 帐户 除了一些被忽略的 a 文件之外 一切看起来都很顺利 我知道它们被忽略 因为除非我使用 no ignore 标志 否则我看不到它们处于
  • SVN 存储库大小莫名其妙地从小差异增加到大文件

    我不明白为什么大文件的微小差异会导致我的颠覆存储库增长如此之多 我有一些测试使用的数据库内容的 zip 文件 我想将每个新版本的测试数据存储在我们的 Subversion 存储库中 我做了一些实验 检查了 data zip 的最后几个版本
  • Maven - 从 SVN 提取代码

    我正在将 J2ee 项目从 Ant 迁移到 Maven ant 任务之一是从 SVN 存储库中提取现有源代码编译它 并将其 jar 添加到我当前的构建中作为 Jar 是否可以获取源代码并在 Maven 中编译它 谢谢你
  • SVN 提交后挂钩在提交后不会运行

    我的服务器上设置了 SVN 存储库 并且遇到提交后问题 我在 iMac 上使用 SmartSVN 作为客户端 我通过 SmartSVN 的 ssh svn 连接 我能够成功连接到 SVN 并对其进行更改 但从 SVN 客户端提交后 我的提交
  • SVN:“相对于其父级已切换”状态是什么意思?

    我正在尝试从 SVN 存储库更新我们的实时站点 据我所知 回购协议中没有任何内容 本身应该与工作副本目录中的任何内容发生冲突 但是当我尝试在公共根目录上 svn up 时 出现以下错误 svn REPORT request failed o
  • 对 Mac“捆绑”文件进行版本控制的最佳方法

    所以你知道很多 Mac 应用程序都使用 捆绑包 对于你的应用程序来说 它看起来像是一个文件 但实际上它是一个包含许多文件的文件夹 对于要处理此问题的版本控制系统 它需要 检出目录中的所有文件 以便应用程序可以根据需要修改它们 at chec

随机推荐

  • 为什么 Rust 链接器在增量构建时没有更快?

    我是 Rust 的新手 我试图理解为什么 Rust 不能更快地构建 我特别讨论的是最常见的情况 其中我对一个源文件做了一个小更改 然后我需要等待几秒钟cargo build做它的工作 即使我的应用程序代码非常小 如果我添加对 MySQL 和
  • TreeMap 按值排序

    我想编写一个比较器 它可以让我按值而不是默认的自然顺序对 TreeMap 进行排序 我尝试了这样的事情 但无法找出出了什么问题 import java util class treeMap public static void main S
  • 如何使用Powershell或其他工具(递归)获取所有AD用户组?

    我试图在我使用的 Powershell 中获取用户所属的所有组 甚至是嵌套的组 重复地 Get ADUser
  • x86 操作码是任意的吗?

    x86 操作码是任意的吗 有没有理由hlt是 0xf4 并且nop是0x90吗 该架构的早期版本 8008 8080 是使用极少量的晶体管 逻辑门来实现的 当时 我确信设计者以易于解码的方式选择了操作码和指令格式 例如 最少的门数 这些说明
  • 如何在hadoop中执行MapReduce作业期间在控制台上打印

    我想在控制台上执行后打印 地图 的每一步 就像是 System out println 第一步完成 System out println 第二步完成 等等 是否有一个特殊的命令可以做到这一点 或者根本不可能 因为 System out pr
  • Flutter - 删除 dart 中的转义序列

    要将 API 响应字符串解码为 JSON json decode 工作正常 这将解析类似于以下内容的 JSON 字符串 Response Responsecode 1 Response Success 但就我而言 响应采用序列化形式 例如
  • SQL语法多重连接?

    我有两个表 Transaction 和 Master 事务表显示了起始和结束活动 ID 主控显示活动 ID 和名称 from 和 to id 使用相同的主表来关联活动 id 和名称 我想做的是采用不同的 from 和 to 值并用关联的名称
  • 从谷歌地图中删除 HeatmapLayer

    我正在使用 HeatmapLayer apihttps developers google com maps documentation javascript layers JSHeatMaps 我像这样生成热图 heatmap new g
  • 在C#中使用FtpWebRequest时设置端口号

    当我尝试使用 VS2008 作为调试器从 C 代码 FTP 到我的 Win 2008 服务器时 我不断收到异常 我的测试类如下所示 public class FTP private string ftpServerIP 192 168 10
  • 比较 BigDecimal

    我有以下两个 BigDecimal 对象 BigDecimal one new BigDecimal 3 0 BigDecimal two new BigDecimal 3 00 System out println one scale 0
  • 三角测量和直接线性变换

    按照 Hartley Zisserman 的多视图几何算法 12 最佳三角测量方法 p318 我得到了相应的图像点 xhat1 和 xhat2 步骤 10 在步骤11中 需要计算3D点Xhat 其中一种方法是直接线性变换 DLT 在 12
  • 如何从Java中的日期获取世纪

    如何从Java中的日期获取当前世纪 例如日期 06 03 2011 根据格式 MM dd yyyy 我怎样才能从这个日期使用当前世纪SimpleDateFormat 哈利 莱姆发布的内容略有变化 他的逻辑并不完全正确 1901 年是 20
  • 为什么要包括警卫?

    包括定义的警卫here 用于防止在编译时两次加载相同的代码 为什么我的编译器 GCC 无法检测到它正在加载相同的代码两次并具有合理的默认行为 仅仅是因为您可能希望编译器加载该文件两次 请记住 那个 include只需加载一个文件并将其内容放
  • 我可以优化 Mercurial 克隆吗?

    我的 Mercurial 克隆变得非常慢 可能是由于磁盘碎片所致 有没有办法优化它 最明显的方法是创建一个新克隆 然后将我的 MQ 保存的捆绑包 hgrc 等复制到新克隆并删除旧克隆 但似乎有人以前遇到过这个问题并进行了扩展来做到这一点 如
  • 如何使用 std::rel_ops 自动提供比较运算符? [复制]

    这个问题在这里已经有答案了 如何获得运营商 gt gt lt and from and
  • 如何在 Python 中检测文件是否为二进制(非文本)?

    在 Python 中如何判断文件是否是二进制 非文本 我正在 Python 中搜索大量文件 并不断在二进制文件中获取匹配项 这使得输出看起来非常混乱 我知道我可以使用grep I 但我对数据的处理超出了 grep 允许的范围 过去 我只会搜
  • “此链接已停用,因为它未嵌入 JSF 表单中。”

    当我使用以下命令链接时
  • 比较悬空指针合法吗?

    比较悬空指针合法吗 int p q int a p a int b q b std cout lt lt p q lt lt n 注意两者如何p and q指向已经消失的物体 这合法吗 介绍 第一个问题是使用价值是否合法p at all A
  • 如何在 Java 中合并两个 XML

    我正在尝试用 Java 合并两个 xml 我正在使用 STaX API 来编写这些 XML 我在互联网上搜索了很多关于如何合并 xml 的信息 但没有一个看起来像C 有没有使用 StAX 在 Java 中执行此操作的直接方法 xslt 可能
  • 您如何组织版本控制存储库?

    首先 我知道这一点 您将如何为内部软件项目组织 Subversion 存储库 接下来 实际问题 我的团队正在重组我们的存储库 我正在寻找有关如何组织它的提示 在本例中为 SVN 这就是我们的想法 我们有一个存储库 多个项目和多个 svn e