SVN子树,从一个仓库更新,提交到另一个仓库



在SVN存储库中有一个大项目。我想在其他应用程序中使用项目的一些模块,所以我考虑从我的主SVN存储库中签出它们,以便我可以保持我的代码更新。

我如何"导出"我的存储库的一个文件夹/模块,以便我可以只签出该模块到其他项目?我想要包含该模块的其他项目也在它们自己的SVN存储库中。

在简历中,我希望能够做SVN更新到主仓库,但做提交到项目仓库。

我希望你能明白我想做什么。

对DavidW的回答:

  • 我有一个存储库与多个项目,但我可能会改变这一点如果有必要的话)。
  • 我想分享源代码。这是一个PHP项目。我我正在分叉模块。(我有一个全局通用项目,如果我的
    客户需要一些特定的功能,
  • 我想为该客户端创建一个单独的项目(在svn中也单独)。但是我想
    有一种方法可以将主项目中的一些更改合并到
    客户端项目。(例如:全局错误修复或功能)。

几个问题:

  • 您是在谈论多个存储库,还是在相同的存储库中的多个项目?
  • 如果你借用了其他模块的代码,你是在保持它与其他模块的同步,还是你在分叉那个模块?
  • 真正想要分享的是什么?您是否必须共享源代码或编译后的输出(Unix C/C+中的*.so*.a, Java中的*.jar等)?

你给出的答案在很大程度上取决于你对这些问题的回答。

让我们假设代码实际上是共享的。你在其中一个做的就是你想在另一个做的。如果您在中更改了项目,则其他项目中的代码也会更改。

使用svn:externals。这是您放置在目录上的属性。它所做的是将Subversion URL关联到子目录名称。例如:

$ svn propset svn:externals "http://svn.vegibanc.com/svn/trunk/project/stuff utils" .

将属性放置在当前目录上。当您执行更新或签出时,将在项目中创建一个名为utils的目录,Subversion将自动将http://svn.vegibanc.com/svn/trunk/project/stuff签入该目录。这是魔法,但就像所有的魔法一样,它也有光明和黑暗的一面。

首先是光明的一面:

这是在两个项目之间共享代码。您在utils目录中进行更改并提交更改,project中的stuff子目录将被更新。我用它在我的项目中构建工具。如果我升级了工具,所有的项目都会得到升级后的工具。

现在,黑暗的一面:

如果你像我给你看的那样定义svn:externals,你会后悔的。想象一下,如果您决定为一个发布版本分支您的工作。那么,您的utils目录仍然指向project/stufftrunk。如果你的分支版本是2.1,而主干现在正在2.2上工作,你会在utils中得到一些你不想要的东西。

更糟糕的是,如果你创建了一个标签,这个标签会继续改变,因为主干中的utils目录仍然在改变。

因此,强烈建议您指定URL的精确的版本:
$ svn propset svn:externals "-r23283 ^/trunk/project/stuff@23283 utils" .
$ svn propset svn:externals "^/tags/2.3.3/project/stuff utils" .

在第一个示例中,我指的是URL的特定的修订。它是完全不变的。如果我需要把它指向另一个版本,我需要改变svn:externals属性本身。

第二个指向一个特定的标记。它不是安全的,因为标签可以更改,但是我可以通过这种方式将我的外部依赖视为一个发布。我使用的是2.3.3版的stuff工具。

两者都使用^快捷方式,它简单地表示 Subversion Repository根。这样,如果您将Subversion存储库移动到另一个系统,或者从http更改到svn,您的外部仍然可以工作。当然,如果您这样做,您将永远无法更改svn:externals下的代码。这不是你想要的。

你也可以使用相对 url,但是它们更危险。

想象一下你的两个项目是这样的,你想让stuff目录和svn:external链接到utils目录:
http://svn.vegibanc.com/svn/trunk/project/foo/stuff
http://svn.vegibanc.com/svn/trunk/project/bar/utils

项目一起分支,一起标记。你可以这样做:

$ co http://svn.vegibanc.com/svn/trunk/project/bar bar-trunk
$ cd project-bar
$ svn propset svn:externals "../foo/stuff utils" .

这会将stuff目录外部链接到utils目录。然而,它是以一种相对的方式完成的。如果你这样做:

$ cp http://svn.vegibanc.com/svn/trunk http://svn.vegibank.com/svn/branches/2.3

你的utils目录仍然会外部链接到foo项目下的stuff目录,但它们都将在2.3分支上。

更改bar/utils中的代码将更改foo/stuff中的代码,反之亦然。你仍然在共享代码,但在某种程度上,两个项目仍然在同一个分支中。

之后,如果你这样标记:

$ cp http://svn.vegibank.com/svn/branches/2.3 http://svn.vegibank.com/svn/tags/2.3.0

你的标签2.3.0不太可能改变,因为外部链接和它们链接到的东西都被那个标签包围了。

上面的假设是你们正在共享代码,并且任何一个项目中的更改都应该影响另一个项目。

更好的方法是让foo创建一个可以存储在发布服务器上的编译对象(如JAR文件或*.so)。您将此编译后的对象视为具有自己版本控制的自己的项目,并且您的项目将依赖于此对象的特定版本。不幸的是,这并不总是有效的。

如果您只是对代码进行分叉,那么从存储库中的一个位置到另一个位置执行svn cp操作。您可以在不影响其他项目的情况下进行更改,反之亦然。更好的是,您可以在两个位置之间来回合并更改,以保持它们的同步。

希望这能回答你的问题。如果你能扩展你的问题,给我们更多你想要的细节,我将能够更新我的答案。

  • 如果你想在Subversion存储库中使用共享代码-它是svn:externals
  • 如果你想从共享代码的主线移植到客户特定版本的共享代码-在svn术语中是"供应商分支"

结合a)和b)会得到你需要的结果

  1. 选择一些节点(客户存储库的主干之外),您将链接到dev-repo中的共享节点
  2. 创建外部定义(如果你需要在提交到dev-repo后手动更新定义的成本,最好使用PEG-revision)
  3. 复制节点到位置,其中in必须在活动项目中(svn cp ...)
  4. 代码…
  5. 当你在dev-repo中有更改时,你想要将其转移到客户repo - update外部以需要的修订,将"Vendor"节点合并到"Live"
示例:

如果你有客户的回购

  • /vendor/lib(其中lib是来自外部repo的目录)*/trunk/common/lib(以上库的客户版本)

将lib-mainline的更改从/vendor/lib合并到/trunk/common/lib(在Working Copy的相应节点中为您的trunk)

David关于外部环境的注释仍然有效、正确和有用

最新更新