我有什么
我有一个C ++代码库, svn 用于VCS。
我的代码使用了多个第三方产品。我们使用每种产品的不同版本,并在不同的操作系统(Linux和Windows)上使用它们。
第三方产品(带有所需版本)存在于编译机器上并在编译时使用,因此代码与使用的第三方版本之间的关系松散耦合。
我想要什么
我想改变这种情况。我们的想法是利用svn vendor branch。 与svn vendor branch中描述的相反,我们将存储第三方产品的二进制版本而不是代码本身。这是因为我们从不修补第三方代码。
svn:external将用于使用适当版本的第三方产品。这是svn存储库的框架:
svn_repo/vendor/product1/OS1/ver1 <- mymodule using it
vendor/product1/OS2/ver1 <- mymodule using it
vendor/product1/OS1/ver2
vendor/product1/OS1/ver2
vendor/product2/OS1/ver1
vendor/product2/OS2/ver1
vendor/product2/OS1/ver2 <- mymodule using it
vendor/product2/OS1/ver2 <- mymodule using it
mymodule/ <- this is my actual code referring to a particular
products from vendor/ using svn:external
mymodule/vendor/product1/OS1 <- reference to vendor/product1/OS1/ver1
mymodule/vendor/product1/OS2 <- reference to vendor/product1/OS2/ver1
mymodule/vendor/product2/OS1 <- reference to vendor/product1/OS1/ver2
mymodule/vendor/product3/OS2 <- reference to vendor/product1/OS2/ver2
问题
在vendor branch章的svn红皮书中,建议保持当前/包含最新版本的第三方产品,因此从示例中我们最终得到:
repos/vendor/libcomplex/current - contains 1.1
repos/vendor/libcomplex/1.0
repos/vendor/libcomplex/1.1
由于我们没有修补第三方代码,所以我认为没有任何意义来保持当前/。 这看起来也必须维护它,因此您可以看到svn提供了辅助perl脚本 svn_load_dirs.pl 来帮助。
我的猜测当前/需要:
我不认为我们真的需要那些。
所以问题是我们是否可以安全地绕过当前/在供应商分支中的处理?
答案 0 :(得分:4)
我们遵循您建议的类似方法,即将供应商二进制文件带入我们的存储库,然后使用svn:externals使用相对路径到这些二进制文件。它工作正常,我喜欢我们没有外部存储库依赖。
您甚至可以考虑为每个操作系统维护每个二进制文件的单个副本,即忘记在目录名称中指定版本,只需使用Subversion版本作为控制器。这是使用svn:externals属性中的显式修订号来完成的,您可能应该这样做。
因此, mymodule / vendor / product1 / OS1 上的svn:externals将设置为 -rXXX ^ / vendor / product1 / OS1 ,其中XXX是包含相应内容的修订版mymodule使用的版本。
例如,在我们的tools目录下,我们有nunit二进制文件。如果nunit发布了新版本,我们会更新tools \ nunit并在日志中记录发布详细信息。引用nunit的所有项目都可以(可选)通过更改相关项目的svn:externals属性的修订版号来开始使用新版本。如果任何项目不想要更新,它们什么都不做:)
答案 1 :(得分:2)
我会说这没关系。这是第三方库的常见情况,您通常没有或想要维护源代码。在这种情况下,完全可以存储您想要的二进制版本,因为从您的产品的角度来看, 是源。
答案 2 :(得分:1)
是的,您可以安全地绕过分支中当前/的处理。在那本书中,他们使用current /作为trunk / for第三方代码,并使用从供应商导入的版本对其进行标记。
答案 3 :(得分:1)
使用'current'目录并设计svn_load_dirs,以便您可以按照自己的说法保留本地更改。它保存了从一个版本到下一个版本的文件的连续历史记录。这允许合并过程检测基础中的更改并允许您保留更改,就像从树干重新分支一个分支一样。否则,每次都将文件视为新文件,并且此'rebasing'尝试完全替换文件而不是合并新位。
由于您正在处理二进制文件而根本没有修补它们,因此您可以放弃它。
答案 4 :(得分:1)
我发现这篇文章对规划我自己的供应商分支很有帮助。但是,我决定为几个版本创建/ current /文件夹,只是为了看看节省的重要性。我想我以后可以删除它,如果它不值得开销。
我决定只将主要版本发布到/ current /,然后为每个主要版本创建一个分支,并将补丁应用到分支。最后,为每个结果级别的代码添加标记。这非常适合供应商的发布模式,其中补丁(版本的第三段保持不变)仅修改所需的文件,但发布(第三段更改)标记每个文件。
15.1.0.1901
-> update trunk
-> copy trunk to new branches/15.1.0
-> copy branches/15.1.0 to tags/15.1.0.1901
15.1.0.2233
-> update branches/15.1.0
-> copy branches/15.1.0 to tags/15.1.0.2233
15.1.1.3064
-> update trunk
-> copy trunk to new branches/15.1.1
-> copy branches/15.1.1 to tags/15.1.1.3064
15.1.0.3299 (bug fix for 15.1.0)
-> update branches/15.1.0
-> copy branches/15.1.0 to tags/15.1.0.3299
供应商代码大约为180MB,主要是带有少量PDB和XML文件的.NET 3.5 DLL。我发现空间节省很大,即使在我从15.1.0到15.1.1的每个DLL都有变化的主干的提交中也是如此。
Version -> size of repos/db/revs file
15.1.0.2782 -> 19,076 KB
15.1.0.2845 -> 78 KB
15.1.0.2892 -> 130 KB
15.1.0.2907 -> 981 KB
15.1.0.2948 -> 1,021 KB
15.1.1.2998 -> 3,334 KB (new branch)
15.1.1.3064 -> 477 KB
假设每次更新的内容都是19MB,我现在最多只需要133MB而不是26MB,节省80%。现在我也不会对磁盘空间感到厌倦,Subversion无论如何都能很好地存储它,但我认为这是一个非常好的节省,非常值得结构和额外的复制操作。
您的里程可能会有所不同。在我的例子中,拥有所有历史版本非常有用:我的团队支持许多客户,每个客户可能使用不同版本的供应商软件。了解供应商更改的文件的取证价值也有助于预测补丁是否会影响我们的增强功能。