SVN:发布分支和外部引用?

16
我们有两个网站为同一个客户服务(主要的www网站和另一个用于电子商务的网站,该网站位于单独的服务器上),它们使用共享的代码部分(各种特色/样式/ JavaScript等)。我们目前通过将共享代码作为单独的项目(在相同的SVN存储库中)管理,并使用svn:externals将每个项目的分支拉入两个网站项目中来管理这些代码。
我们刚刚创建了两个发布分支,分别是为两个网站准备的。当我们工作时,将所有内容都提交到每个站点的trunk中。当“准备好上线”后,我们将其合并到该站点的发布分支中。这一切都很顺利,除了今天我们修改了一些共享代码,并注意到在更新发布分支时会立即引入这些代码。这不是我们想要的:(
那么,有什么办法可以解决这个问题吗?我们使用外部文件来简化代码共享,但是否还有其他方法?在这个问题(如何在SVN中分支,让它同时分支我的svn:external文件夹?) 中,他们提到外部文件不好,我们应该使用不同的构建进程,但没有提到应该使用什么。
我们正在使用CruiseControl.net来运行构建,并渴望解决这个问题。有人对更好的流程有任何想法吗?
谢谢
彼得
更新:我们已经转向使用Mercurial(Fogcreek's Kiln)作为我们的源代码控制。Mercurial也有子存储库的概念,因此我们也采用了该方法。然而,这是有代价的,分支变得非常困难,标记和简单地保持一切最新也很困难。我们的最新方法是将两个项目并入一个存储库中,包括所有共享存储库。这给我们带来了一个“超级项目”,这会减慢克隆时间(在SVN中检查),但我们很少这样做,不必处理子存储库的利益使其非常值得。我们现在使用功能切换/切换而不是分支,这也极大地简化了我们的开发。
5个回答

20
  • 通过 svn:externals library svn://repo/library 进行链接的库目录
  • branches
    • release1
      • 通过 svn:externals library svn://repo/library 进行链接的库目录,将自动获取最新版本
    • release2
      • 通过 svn:externals library svn://repo/library 进行链接的库目录,将自动获取最新版本
  • project2
    • trunk
      • 通过 svn:externals library svn://repo/library 进行链接的库目录
    • branches
      • release1
        • 通过 svn:externals library svn://repo/library 进行链接的库目录,将自动获取最新版本
  • library
  • 我假设您正在 /project1/trunk 上设置 svn:externals ,链接到 /library 目录。如果您将具有 svn:externals 的版本合并到 /project1/branches/release1 并更新该分支,则将自动获取来自库的最新版本。默认情况下,svn:externals 将获取链接的 HEAD 版本。

    您可以定义 svn:externals 以链接到特定版本,例如:svn:externals -r123 library svn://repo/library。这意味着外部链接将始终指向该特定版本。因此,您可以安全地在发布分支中使用此类型的 svn:externals 链接,而无需担心共享库代码会自动更新,除非您手动更改了 svn:externals

    也许更好的方法是使用标签对共享库进行版本控制,并链接到特定标签。在这种情况下,您会获得以下存储库结构:

    • project1
      • trunk
        • 通过 svn:externals library svn://repo/library 进行链接的库目录
      • branches
        • release1
          • 通过 svn:externals library svn://repo/library 进行链接的库目录,将自动获取指定标签下的版本
        • release2
          • 通过 svn:externals library svn://repo/library 进行链接的库目录,将自动获取指定标签下的版本
    • project2
      • trunk
        • 通过 svn:externals library svn://repo/library 进行链接的库目录
      • branches
        • release1
          • 通过 svn:externals library svn://repo/library 进行链接的库目录,将自动获取指定标签下的版本
    • library
  • 库(通过 svn:externals library svn://repo/library/tags/version3
  • 分支
    • 发布1
      • 库(通过 svn:externals library svn://repo/library/tags/version1
    • 发布2
      • 库(通过 svn:externals library svn://repo/library/tags/version2
  • 项目2
    • 主干
      • 库(通过 svn:externals library svn://repo/library/tags/version2
    • 分支
      • 发布1
        • 库(通过 svn:externals library svn://repo/library/tags/version1
    • 标签
      • 版本1
      • 版本2
      • 版本3

  • 啊,现在这样就好多了。顺便说一下,写得很好。谢谢。我想把主干引用外部库的HEAD留下来应该是安全的,但我的发布版本要指向一个已标记的版本。这样安全吗?最近我一直在困扰这个问题,自己也陷入了混乱之中。感谢您的清晰解答。 - Pete Duncanson
    @Pete Duncanson:我已经尝试过这种方法(让项目主干引用外部库的HEAD版本,但是我的发布版本指向一个已标记的版本),并没有注意到任何重大问题。 - Paul Walker
    你是否会遇到问题完全取决于你所引用的svn:external代码。如果代码是向后兼容的(相同的方法、类和行为,只有新的内容不同),那么你就不会遇到任何问题。然而,如果你对类、方法或代码的一般行为进行了更改,那么你的项目即使能编译也算是幸运的了。 - Jesse Webb
    补充回答:@PeteDuncanson 把你的“library”看作是有它自己的开发生命周期(因此有自己的标签/分支/主干和版本发布)。理论上,您可以有一个独立的团队按照自己的时间表维护它(但实际上这很大程度上是同一团队)。在您的“trunk”中使用他们的“HEAD”可能会不稳定,并且您将不知道该“HEAD”处于哪个稳定的发布版本。相反,使用外部链接到“release”分支,以便您知道在trunk中使用v1.9的库,并在可用时有意识地将其更新为新的(稳定的)版本。 - Wasted_Coder
    另一个更实际的建议是将该库集成到主要控制它的项目中。然后在其他项目中使用svn:externals指向该主项目的release分支,但直接指向库,例如project1/branches/release1/library。这将直接将库版本与主项目版本耦合在一起,但确保了project1/trunk内库中的破坏性更改不会影响其他项目,同时它们的发布版本也会跟踪主项目库的特定版本。 - Wasted_Coder

    3

    Otherside提供了一些很好的建议,但实际上它是将svn:externals用作贫民依赖管理系统。 它使一个hacky反模式对于纪律严明的人来说有点可行。

    您绝对正确,svn:externals不是正确的路径。

    还有一件事要考虑,如果您沿着这条路走 - 除非您的svn标签是原子的(通过预提交钩子),否则您将需要指定修订版本以及标签。

    我目前正在遭受一些.NET东西的负担,让我非常想念maven。 我甚至会接受ant / ivy的混乱。

    您可能想查看 https://www.nuget.org/


    1

    如果您不想更新外部内容,可以执行svn update --ignore-externals命令。


    我认为外部依赖可能并不是最好的选择。我的问题在于当我想要将它们更改为发布分支时,从外部依赖中进行更改非常困难,目前无论何时更新都会添加它们。当前设置的唯一解决方案是为每个外部依赖创建发布分支,但这很快就变成了一个难以管理的噩梦,太多事情要处理。因此,我认为在这种情况下,外部依赖是一条死路。 - Pete Duncanson

    1
    是的,使用指向特定修订版或标签的外部资源是正确的做法。你只需阅读一下svn的外部资源手册就可以轻松地找到这个信息... RFD!而且,它只有一页长... :)

    http://svnbook.red-bean.com/en/1.0/ch07s03.html


    4
    最近我一直在阅读,同时还要在项目紧张的情况下更新我们的构建服务器以方便发布分支版本,并招聘新员工(总人数已达到3人!),但由于我们没有足够的流程措施,两个网站出了问题。所有这些信息很容易让人精疲力尽。我发帖并不是因为懒惰,而是因为沮丧、疲惫和困惑。到目前为止,这篇帖子值得花费悬赏金。感谢你的回答 ;) - Pete Duncanson

    0

    我正在创建发布/稳定分支,通过复制外部文件夹,使得分支完全独立于主干。使用以下命令进行svn复制:

    svn copy --parent

    ...到它们各自的挂载点。未经修订的外部文件夹使用您想要根据其创建分支的版本;已经修订的外部文件夹在复制时使用它们指定的版本。 然后必须在新分支中删除svn:externals属性。

    一些脚本(对我来说是perl)可以帮助自动化此过程。如果需要更多信息,请联系我。


    但这并不能解决我的问题。我们在主分支上的工作中会对外部进行更改。这样做会丢失历史记录,而且无法通过手动差异比较来确定所做的更改。我们使用我编辑中的方法解决了这个问题。 - Pete Duncanson
    好的,我以为你正在寻找与一切隔离且可以独立于外部和主干进化的发布分支。顺便说一下,“svn copy”不会使我失去历史记录,因此自动合并仍然是可能的。无论如何,很高兴你找到了解决方案。 - bm842

    网页内容由stack overflow 提供, 点击上面的
    可以查看英文原文,
    原文链接