在 SVN 中构建大型多应用程序代码库的正确方法是什么

发布于 2024-09-26 16:14:41 字数 539 浏览 5 评论 0原文

我们目前有一个带有 codesion 的存储库,http://John.svn.cvsdude.com,具有单个 SVN 项目 http://John.svn.cvsdude.com/MyProject,其中包含单个 Visual C++ 解决方案的几个子目录

这一切都是从一个应用程序开始的,尽管我们确实拆分了单独的库项目以供将来重用,但它仍然是相同的 SVN 项目。假设我们的目标是拥有多个应用程序,并且使用的库有一些重叠,那么在 SVN 中设置它的正确/最佳方法是什么?当然,人们可以只保留一个 SVN 项目,并将应用程序项目和库项目作为子目录,但这似乎不太正确。

假设我们有 App1、App2、App3 和 LibraryA、LibraryB、LibraryC、LibraryD,其中这些都是单独的项目/解决方案...您将如何在一个(或多个存储库)下组织它们?有最佳实践吗?

We've currently got a single repo with codesion, http://John.svn.cvsdude.com, with a single SVN project http://John.svn.cvsdude.com/MyProject, which contains a few subdirs for individual Visual C++ solutions

This all started as one application and though we did split off separate library projects for future re-use, it's still all the same SVN project. Lets say we aim to have multiple applications with some overlap in libraries used, what's the right/best way to set this up in SVN? Of course one could just keep one SVN project and put app-projects and library-projects as sub-dirs, but it hardly seems right somehow.

Say we have App1, App2, App3 and LibraryA, LibraryB, LibraryC, LibraryD where these are all separate projects/solutions... how would you organise this under one (or more repos)? Is there a best-practice?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(3

爱的十字路口 2024-10-03 16:14:41

我将将所有内容保留在一个存储库中,并将每个项目和库放在存储库的单独根目录中(请参阅规划您的存储库组织了解详细信息)。

请记住,存储库结构不必与磁盘上的项目文件结构相同。

另外我会使用svn-externals在各个项目之间共享库目录(作为存储库的单独根文件夹保存)。

I would keep everything in one repository and put each project and library in separate root directory of repository (see Planning Your Repository Organization for details).

Keep in mind that repository structure do not have to be identical to project files structure on disk.

Also I would use svn-externals to share library directories (kept as separate root folders of repository) among various projects.

痴者 2024-10-03 16:14:41

我是来自 Codesion 云服务公司 CollabNet 的 Jack。首先,感谢您成为 Codesion 客户!

您用“项目”来描述您的情况,但这是一个含糊不清的术语,Subversion 本身根本没有任何概念。这里真正考虑的不是 Subversion 本身,而是你的构建工具和发布策略。您需要最能支持您想做的事情的配置。

例如,所有这些应用程序和库是否一次性全部发布?完全独立?一些混合?这个答案可能会改变吗?

如果它们全部同时发布,那么尽可能轻松地识别每个应用程序的哪些版本与其他应用程序的哪些版本一起发布就具有重要价值。这样,就可以以连贯、一致的方式验证错误报告、实施修复以及合并补丁。为了实现这一目标,我不会使用一些人建议的“/app/{trunk,tags,branches}”结构,而是坚持使用规范

/trunk/app1
/trunk/app2
/tags/TAGNAME/app1
/tags/TAGNAME/app2
/branches/BRANCHNAME/app1
/branches/BRANCHNAME/app2

结构。这允许您在一个命令中分支、标记和合并整个树、所有应用程序和库:

svn cp URL/trunk URL/tags/TAGNAME

另一方面,如果这些东西是独立的,那么您最好使用

/app1/trunk
/app1/tags
/app1/branches
/app2/trunk
/app2/tags
/app2/branches
...

这种方式,例如,标记一个应用程序不会影响另一个应用程序。

在混合情况下,您仍然可以实现协调分支(在适当的情况下),但您必须在工作副本中使用分支,并且可能需要稀疏检出(如果工作副本很大)。或者,您可以标记或分支整个存储库,即使标记或分支对于其中大部分没有意义:Subversion 标记和分支的存储成本很低,并且(如果您使用“svn cp 的 URL 到 URL 形式”) ") 制造成本低廉;不要用不相关的标签来标记事物的唯一原因是,它会让人类感到困惑。但这是一个非常有力的原因,因此混合模型最好使用“应用程序/主干”结构来处理,以避免混淆。

您可以在 Apache Foundation 存储库中找到“/app/trunk”方法的好示例。所有 Apache 项目(包括 Subversion 本身)都存储在单个 Subversion 存储库中。那里有大约 100 个项目,尽管存在一些相互依赖关系,但它们几乎都是独立管理的。您可以从 所有 ASF 项目的根目录。实践中存在一些多样性,但一个很好的例子是 颠覆本身

另外值得注意的是:就 Subversion 而言,您可以随时更改这些内容。 “标签”和“分支”实际上只是副本;你可以在你喜欢的时候自由地重新安排事情。但有一些警告:

  • 它会让人类感到困惑
  • 。 “树冲突”(添加、删除、移动或重命名文件或目录)可能会使以后的合并变得痛苦。合并工具的作用是节省您的工作量。所有合并工具最终,为了进行足够困难的合并,将决策权交还给人类;重要的问题是,如果没有这一点,他们能在多大程度上做到正确。树冲突会导致当前的 Subversion(1.6 或更高版本)比您希望的更频繁地进行下注。因此,最好不要过于频繁地重新排列顶级目录,并准备好干预和清理任何跨越此类重新排列的合并。

this is Jack from CollabNet, Codesion Cloud Services. First, thank you for being a Codesion customer!

You describe your situation in terms of "projects," but that's an ambiguous term, and Subversion itself hasn't any notion of it at all. The real consideration here is not Subversion per se, but your build tools and release policy. You want the configuration that best supports what you want to do.

For example, do all these apps and libraries release all at once? Completely independently? Some mix? Is that answer likely to change?

If they all release at once, then there's important value in making it as easy as possible to identify which versions of each app were released with which versions of other apps. That way, bug reports can be verified, fixes implemented, and patches merged all in a coherent, consistent way. To achieve this, I would not use the "/app/{trunk,tags,branches}" structure that several have suggested, but rather stick with the canonical

/trunk/app1
/trunk/app2
/tags/TAGNAME/app1
/tags/TAGNAME/app2
/branches/BRANCHNAME/app1
/branches/BRANCHNAME/app2

structure. This allows you to branch, tag, and merge the whole tree, all apps and libraries, in a single command:

svn cp URL/trunk URL/tags/TAGNAME

On the other hand, if these things are independent, then you're better off with

/app1/trunk
/app1/tags
/app1/branches
/app2/trunk
/app2/tags
/app2/branches
...

This way, for example, tagging one app doesn't affect another.

In a mixed case, you can still achieve the coordinated branching (when it's appropriate), but you'll have to use branching from within your working copy, and perhaps sparse check-outs (if the working copies are large). Alternately, you can tag or branch the whole repository, even though the tag or branch has no meaning for most of it: Subversion tags and branches are cheap to store, and (if you use the URL-to-URL form of "svn cp") cheap to make; the only reason not to tag things with unrelated tags is, it confuses the humans. But that's a pretty strong reason, so a mixed model is best handled with the "app/trunk" structure, to avoid confusion.

You can find good examples of the "/app/trunk" approach in the Apache Foundation repository. All the Apache projects (including Subversion itself) are stored in a single Subversion repository. There are around 100 projects there, and although there are some interdependencies, they're all pretty much managed independently. You can browse around this giant repo (possibly the largest single Subversion repo in the public world), starting at the root of all ASF projects. There's some diversity in practice, there, but one good example is Subversion itself.

Also worth note: in so far as Subversion is concerned, you can always change this stuff. The "tags" and "branches" are really just copies; you're free to rearrange things as you like, when you like. But there are some cautions:

  • It'll confuse the humans
  • "Tree conflicts" (addition, deletion, moving, or renaming files or directories) can make later merges painful. The function of a merge tool is to save you work. All merge tools eventually, for a hard enough merge, punt the decisions back to the humans; the important question is how much they can get right without that. Tree conflicts cause current Subversion (1.6 or better) to punt way more often than you'll like. So, it's best not to rearrange top-level directories like these too often, and be prepared to intervene and clean up for any merges that cross such rearrangements.
呆头 2024-10-03 16:14:41

我建议使用以下布局,全部在同一个存储库中:

App1\
    trunk
    tags
    branches
App2\
    trunk
    tags
    branches
App3\
    trunk
    tags
    branches
LibraryA\
    trunk
    tags
    branches
LibraryB\
    trunk
    tags
    branches
LibraryC\
    trunk
    tags
    branches
LibraryD\
    trunk
    tags
    branches

现在,我对您的发布时间表做出一些假设。我假设每个应用程序和库都是根据不同的时间表发布的。这实际上是最坏的情况,但我的方案允许这样做。每个应用程序都需要预编译其依赖项并将其包含在存储库中的目录中。考虑到 App1 依赖于库 B 和 C,App1 的外观如下:

App1\
    trunk\
        deps\
            LibraryB, release 1.1
            LibraryC, release 4.3
    tags
    branches

这意味着每当您分支主干时,您都会获得必要的库,这大大简化了事情。请注意,它是库的编译二进制文件,而不是它们的源代码。

trunk的一个分支将使用上述版本,并且由于您不允许修改它们,因此任何错误修复都需要进入App1。同时,要使用新版本的 LibB&C,当库团队发布它们时,您可以在主干中更新它们的版本。因此,一段时间后,您的存储库可能如下所示:

App1\
     trunk\
         deps\
             LibraryB, release 1.3
             LibraryC, release 4.4
     tags\
         release-1.0\
             deps\
                 LibraryB, release 1.1
                 LibraryC, release 4.3
     branches\
         stable-2.0\
             deps\
                 LibraryB, release 1.2
                 LibraryC, release 4.2

允许主干中的工作使用最新的库版本。 release-1.0 使用固定版本(此处为最旧版本),而稳定分支使用以前版本的库。

上述计划是我在上一家公司时思考了很多,但从未抽出时间实施的。为了使其工作,您需要有一个分为应用程序/库的代码库,并且开发可以并行进行。我们的情况并非如此。但我坚信,这是一个有价值的目标。

祝你好运!

PS 我强烈推荐反对 svn:externals。它们会使分支机构管理变得更加困难。例如,如果外部发生更改并且分支依赖于它,那么您就有可能搞乱该分支(例如使其无法编译)。

I would recommend the following layout, all in the same repository:

App1\
    trunk
    tags
    branches
App2\
    trunk
    tags
    branches
App3\
    trunk
    tags
    branches
LibraryA\
    trunk
    tags
    branches
LibraryB\
    trunk
    tags
    branches
LibraryC\
    trunk
    tags
    branches
LibraryD\
    trunk
    tags
    branches

Now, I am making a few assumptions about your release schedule. I am assuming that each application and library are released under different schedules. This is a worst-case scenario actually, but my scheme will allow this. Each application needs to have its dependencies pre-compiled and included in its directory in the repository. Here's how App1 would look, given that it has dependencies on Library B and C:

App1\
    trunk\
        deps\
            LibraryB, release 1.1
            LibraryC, release 4.3
    tags
    branches

This means that whenever you branch trunk you will get the necessary libraries along, which greatly simplifies things. Observe that it is the compiled binaries of the libraries, not their sources.

A branch of trunk will use the above versions, and since you're not allowed to modify them, any bugfixes will need to go into App1. Meanwhile, to use the new versions of LibB&C you can update their versions in trunk, when they are released by the libraries team. So, after some time, your repository might look like this:

App1\
     trunk\
         deps\
             LibraryB, release 1.3
             LibraryC, release 4.4
     tags\
         release-1.0\
             deps\
                 LibraryB, release 1.1
                 LibraryC, release 4.3
     branches\
         stable-2.0\
             deps\
                 LibraryB, release 1.2
                 LibraryC, release 4.2

Work in trunk is allowed to use the latest library releases. The release-1.0 is using fixed releases (oldest version here), while the stable branch is using the previous version of the libraries.

The above scheme is something I thought about a lot at my last employer, but never got around to implementing. To make it work you need to have a codebase that is split into applications/libraries and development can take place in parallel. That wasn't really the case for us. But it is a worth-while goal, I strongly believe.

Good luck!

P.S. I strongly recommend against svn:externals. They can make branch management a lot harder. For example, if an external changes and a branch is dependent upon it, you are under risk of messing up that branch (making it uncompilable for example).

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文