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

4
我在一个 SVN 仓库中有一个大项目。我想在其他应用程序中使用该项目的某些模块,所以我考虑从我的主 SVN 仓库中检出它们,这样我可以保持我的代码更新。
我如何“导出”存储库中的一个文件夹/模块,以便我只能将该模块检出到其他项目中?我要包含该模块的其他项目也在它们自己的 SVN 存储库中。
简而言之,我希望能够对主仓库进行 SVN 更新,但对项目仓库进行提交。
我希望我的意图清楚明了。
回答 DavidW 的问题:
- 我有一个具有多个项目的仓库,但如果需要,我可能会更改此设置。 - 我想共享源代码。它是一个 PHP 项目。我正在派生该模块。(我有一个全局通用项目,如果我的客户需要一些特定的功能, - 我想为该客户创建一个单独的项目(在 svn 中也是分开的)。但我想找到一种方法将主项目中进行的一些更改合并到客户项目中。(例如:全局错误修复或功能)。

据我所见,您已经在标签中指定了 svn:externals。那么问题是什么?请参阅相关文档:http://svnbook.red-bean.com/en/1.7/svn.advanced.externals.html 和 http://tortoisesvn.net/docs/release/TortoiseSVN_en/tsvn-howto-common-projects.html#tsvn-howto-common-externals - bahrep
2个回答

1
一些问题:
  • 您是在谈论多个存储库,还是同一存储库中的多个项目?
  • 如果您“借用”另一个模块的代码,您是否会将其与该模块保持同步,还是会分叉该模块?
  • 您真正想要分享什么?必须分享源代码还是已编译的输出(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版本创建分支,而trunk现在正在处理2.2版本,那么您将会得到一些您不想要的utils内容。
更糟糕的是,如果您创建了一个标签,那么该标签将继续更改,因为trunk中的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属性本身。
第二种情况是指向特定标记。这不太安全,因为标记可能会更改,但是我可以将我的外部依赖项视为发布。我正在使用stuff实用程序的2.3.3版本。
两者都使用^快捷方式,它仅表示Subversion Repository Root。这样,如果您将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从存储库中的一个位置复制到另一个位置。您可以在不影响其他项目的情况下进行更改,反之亦然。更好的是,您可以在两个位置之间来回合并更改,以使它们保持同步。

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


嗨,David。我已经在我的帖子中回答了你的问题。根据你的回答,我认为我需要的是cp命令。我可以为每个客户项目创建一个分支/标签,例如,如果我在主分支中进行了一些错误修复,我可以将该错误修复与所有客户项目的分支合并。我理解得正确吗?非常感谢您详细的回答。 - brpaz
@Bruno-P 是的。如果您的项目与其他项目在同一个代码库中,并且您不希望更改完全同步,最好的处理方法是使用 svn cp 创建您的项目。来自一个项目的代码更改不会自动显示在另一个项目中。但是,您可以使用svn merge来同步更改。 - David W.

1
  • 如果您想在Subversion存储库中使用共享代码 - 使用svn:externals
  • 如果您想将主干上的共享代码更改移植到特定于客户的版本中 - 这是svn术语中的"供应商分支"

结合a)和b),将为您提供所需的结果

  1. 选择某个节点(位于客户端存储库的主干之外),将其链接到开发存储库中的共享节点
  2. 创建外部定义(最好使用PEG修订版,如果您需要轻松的时间回退,则需要手动更新定义后提交至dev-repo)
  3. 将节点复制到必须在实时项目中的位置(svn cp ...
  4. 编码...
  5. 当您在dev-repo中有更改要传输到客户端repo时 - 更新外部到所需的修订版,将"Vendor"节点合并到"Live"

示例:

如果您在客户端repo中有以下内容

  • /vendor/lib(其中lib是来自外部repo的目录) */trunk/common/lib(上述lib的客户端版本)
将来自lib-mainline的更改合并从/vendor/lib到/trunk/common/lib(在您的主干的相应节点的工作副本中)。
关于外部依赖项,David的笔记仍然有效,正确且有用。

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