在另一个svn:externals中使用svn:externals的麻烦

时间:2013-04-03 13:34:29

标签: svn svn-externals

我在检查svn存储库中的标记版本时遇到了一些麻烦,很可能是因为内部'svn:externals'没有引用正确的修订版。让我们考虑简化的情况:

我有一个第一个svn存储库,在修订版XXX1中看起来像这样:

Repo1 (@ Rev XXX1)
  tags
    ...
  trunk
    Folder1
      ExternalRefToFolder2 (svn:externals '../Folder2')
    Folder2
      SomeFile1.txt
      SomeFile2.txt

已经重构(在修订版时):

Repo1 (@ HEAD1)
  tags
    ...
  trunk
    Folder1
      SomeFile1.txt
      SomeFile2.txt

I.E:对于好的或坏的,Folder2的外部引用已被删除,并由修订版XXX1HEAD1之间的文件副本替换。

我在同一台服务器上也有第二个存储库,如下所示:

Repo2 (@ HEAD2) 
  tags
    1.0.0
      ExternalToRepo1 (svn:externals -rXXX1 ^/../Repo1/trunk)
  trunk
    ExternalToRepo1 (svn:externals ^/../Repo1/trunk)

IE:同样,对于好的或坏的,第二个存储库使用外部引用引用第一个存储库(HEAD1中的修订版trunk和标记版本中的修订版XXX1至于在正确修订时冻结所有内容。)

问题

  • 当我退出trunk的{​​{1}}时,我没有任何问题。这是Repo2使用单Repo1签出。

  • 当我查看Folder1的标记1.0.0时,svn会抱怨它在Repo2修订时找不到http://server//Repo1//trunk//Folder2

即使标记HEAD1在其正确的1.0.0版本中引用Repo1/trunk,所以看起来都是如此; 内部外部XXX1被解释为基于svn:externals '../Folder2'(而不是我预期的版本HEAD1)。

这种行为是否正常,我该如何处理这个问题呢?

注意:我的Svn版本是2012年12月12日编制的1.7.8(r1419671)

修改

重现此问题的另一种方法是退房或只是浏览修订版XXX1中的Repo1XXX1然后仍然会相对于svn:externals '../Folder2',所以猜测没有太多解决方案。

2 个答案:

答案 0 :(得分:2)

第一眼看起来有点奇怪,但你会发现它接下来就像预期的那样。

SVN为特定提交集分配修订号,该修订号不仅包含更改,还包含通过svn副本创建的目录,文件,属性和链接(所谓的标记或分支)的添加或删除。 SVN并不真正复制目录,因为它来自文件系统,而是将目录链接到新目录。删除所有链接(原始目录和复制目录)后,内容将被删除"暂停" (但实际上没有删除)在SVN历史的深处。您可以随时更新到最新修订版,其中包含指向目录内容的最后一个链接。

外部就像您可以设置到外部存储库的链接,但与链接相反的链接始终由同一存储库维护,外部内容实际上不会被暂停"因为它是从另一侧控制的,来自包含外部内容的存储库。换句话说,存储库包含一个外部链接,存储库中存储了一个内容,它可以维护完全不同的地址并位于不同的机器上。

这就是为什么在必须为外部链接设置正确的修订号时会发生什么样的错误,否则将采用最后一个,即HEAD。当内容已经缺席时,您的ExternalRefToFolder2会进行头部修订。可以显式设置外部修订版本,也可以使用svn copy。

但请记住,svn copy会创建链接,但会创建自己的内容历史记录。这意味着所有对链接到修订版Folder2的提交都不会通过链接到版本的ExternalRefToFolder2 / Folder2来改变内容,反之亦然。

所以以同样的方式处理嵌套链接和外部。这只是另一个参考水平。您必须在从根目录中获取精确目录树结构/内容的方式上为所有外部设置(并提交相关属性)特定修订。

答案 1 :(得分:1)

使用svn:externals作为穷人的依赖管理或代码重复避免方案是您的困境的根源。嵌套它们不是双坏的,它是乘法的。 我推荐这个excellent long answer about the badness with externals

使用svn:externals作为内部资源,你永远不会有很好的结果,但是如果你继续使用它们,你可以减轻痛苦:

  1. 遵循red book的建议,永远不要在外面拉一下:
  2.   

    您应该认真考虑在所有外部定义中使用显式修订号。这样做意味着您可以决定何时下拉外部信息的不同快照,以及确切地提取哪个快照。除了避免对您可能无法控制的第三方存储库进行更改的意外之外,使用显式修订号还意味着当您将工作副本回溯到以前的版本时,您的外部定义也将恢复为它们的外观在之前的修订版中,这反过来意味着将更新外部工作副本以匹配当您的存储库处于该先前版本时它们回顾的方式。对于软件项目,这可能是复杂代码库的旧快照的成功构建和失败构建之间的差异。

    1. 如果您不执行上述操作,请使用svncopy.pl创建代码。它会将您的外部修改“固定”到创建标记时的任何内容。
    2. 您没有提到为什么您有多个存储库 - 您是否有可能从合并中受益? 你没有提到你使用的语言/工具。我很确定你有更好的方法来满足你的要求。例如,如果它是一个带有一些库的Java应用程序,你通过外部引入 - 如果你单独构建库并使用类似物质的maven发布它们,然后在构建应用程序时解决它们,你会更高兴。