调整svn:外部用法以迁移到Mercurial [英] Adapting svn:externals usage for move to Mercurial

查看:76
本文介绍了调整svn:外部用法以迁移到Mercurial的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我们在公司环境中拥有一个svn存储库结构,如下所示:

root
  libs
    shared_lib1
    shared_lib2
    private_lib
  public_code
  private_code

其中public_code是一个开放源代码的外部存储库,并且公司外部的人员都具有读写访问权限. shared_lib1和shared_lib2也是与其他公司的另一组程序员共享的外部存储库.我是维护者,基本上可以做任何技术上最好的事情,外部用户将不得不适应.

我现在想知道从这种结构迁移到商品库的最佳方法是什么.

1)我可以使用Mercurial子存储库严密模拟旧设置. OR
2)我可以为我们做一个大型的仓库,为外部合作伙伴做三个新的较小的,独立的存储库(基本上是分叉的项目),并在大型仓库和独立的仓库之间交换变更集.

在svn中使用设置1)时,分支是一场噩梦,因为根据我的策略,当我分支root时,我总是必须分支public_code,shared_lib1和shared_lib2.为此,我必须调用svn分支四次,并手动修改svn:externals属性三遍.我可以轻松地在Merurial中分支主仓库并自动为所有子仓库获取新分支吗?

当我执行设置2)时,存储库之间的文件系统将有所不同.例如.我在回购"root"中将有public_code/Makefile,但是在回购"public_code"中文件将只是"Makefile". Mercurial仍然能够在存储库之间同步更改吗?工作流程看起来如何?

解决方案

在SVN中使用设置1)时,分支是一场噩梦,因为根据策略,我在分支root时始终必须分支public_codeshared_lib1shared_lib2.为此,我必须调用4次svn branch并手动修改3次svn:externals属性.我可以轻松地在Mercurial中分支主存储库并为所有子存储库自动获取新分支吗?

不,子存储库不能那样工作.顶级存储库中的命名分支不会自动传播到子存储库.如果在代码中创建1.x分支,则不清楚shared_lib1是否也应具有1.x分支.实际上,它可能不应该在顶级代码分支的同时分支,特别是如果该库正由多个不同的顶级项目使用.

当我执行设置2)时,存储库之间的文件系统将有所不同.例如.我在回购root中将有public_code/Makefile,但是在回购public_code中文件将只是Makefile. Mercurial仍然能够在存储库之间同步更改吗?工作流程看起来如何?

不,如果这样创建存储库,则无法在存储库之间进行推拉.当存储库来自同一母"存储库时,只能在存储库之间进行推/拉.在这里听起来您将创建三个不相关的存储库.


在这种情况下,您应该仔细评估为什么您在Subversion中拥有svn:externals以及它们如何映射到 Mercurial子存储库.它们不是svn:externals的1-1替代.您还应该研究对子仓库的工具支持—在Mercurial本身以及您的Mercurial托管,您的持续构建系统中,等等.我编写了Mercurial子仓库代码的一部分,而从Mercurial 2.0开始,到处都是.

简而言之,子存储库为您提供的是子系统之间的非常紧密的耦合.通常这是要避免的事情:-)我们努力使我们的软件系统松散耦合,因为这样做可以给我们带来灵活性.

子存储库的主要用例是构建存储库",您可以在其中跟踪在给定构建中使用的组件的精确版本.您不能要求Mercurial跟踪子仓库中给定分支的尖端,它将始终跟踪给定存储库中给定的变更集.这样便可以在以后重新创建给定的检出:.hgsubstate文件跟踪在每个子存储库中检出的精确变更集.

因此,如果您的root存储库不用于开发,而仅用于构建发行版,那么子存储库实际上可以为您工作.工作流程将类似于

$ cd root
$ cd libs/shared_lib1
$ hg pull
$ hg update 2.0
$ cd ../..
$ make test && hg commit -m "Updated to sharedlib1 2.0"
$ hg tag 2.3

然后您发布软件的2.3版,Mercurial知道它取决于shared_lib1的2.0版.当负责这些子组件的人员告诉您他们已经为您准备了新版本时,您将不时执行此操作.您的CI服务器当然可以每晚执行此操作,以查看组件是否可以协同工作!

如果开发人员直接在root中工作,并且作为他们在root中工作的一部分对子组件进行更改,则

子存储库的工作情况会较差.这表明组件之间的耦合太紧密:如果主代码依赖于子组件的精确变更集,那么子组件应该直接位于主代码中.同样,顶级存储库中的hg commit将递归并在ui.commitsubrepos=True时在子存储库中使用相同的提交消息. (在Mercurial 2.0中,默认设置更改为False.)通常不希望这样做,并且在确实有意义时,然后将子存储库耦合得非常紧密,应该将其作为顶级存储库的一部分.

因此,总结一下:如果root是构建存储库",请使用subrepos.否则,您应该内联顶级存储库中的组件,或者应该使用 Maven 或类似的东西来管理依赖项.这些工具通常会让您说请使用root的最新版本及其所有依赖项",然后在对测试感到满意时可以进行正式发行.这些快照"版本无法精确复制,但是也不需要-仅最终版本需要严格而精确的依赖项跟踪.

We've got in a corporate environment an svn repository structure which looks like this:

root
  libs
    shared_lib1
    shared_lib2
    private_lib
  public_code
  private_code

where public_code is an external repository which is open source and where people from outside the company have read-write-access. shared_lib1 and shared_lib2 are also external repositories shared with a different group of programmers from an other company. I'm the maintainer and can do basically whatever is technically best, the outside users will have to adapt.

I'm now wondering what the best way is to move from this structure to a mercurial repository.

1) I could closely simulate the old setup using mercurial subrepositories. OR
2) I could make one big repo for us and three new smaller, separate repositories for the external partners (so basically forking projects) and exchange changesets between the big one and the separate ones.

With setup 1) in svn, branching is a nightmare because I by policy always have to branch public_code, shared_lib1 and shared_lib2 when I branch root. For this I have to call svn branch four times and modify svn:externals properties by hand three times. Can I easily branch the main repo in mercurial and get automatically new branches for all sub-repositories?

When I do setup 2), the file system will be different between repos. E.g. I will have public_code/Makefile in repo "root" but the file will be just "Makefile" in repo "public_code". Will Mercurial still be able to synchronize changes between the repos? How could the workflow look like?

解决方案

With setup 1) in SVN, branching is a nightmare because I by policy always have to branch public_code, shared_lib1 and shared_lib2 when I branch root. For this I have to call svn branch four times and modify svn:externals properties by hand three times. Can I easily branch the main repo in Mercurial and get automatically new branches for all sub-repositories?

No, subrepositories don't work like that. Named branches in the top-level repository will not propagate to subrepositories automatically. If you make a 1.x branch in your code, then it's not clear that shared_lib1 should also have 1.x branch. In fact, it probably shouldn't branch at the same time the top-level code branches, especially if the library is being used by several different top-level projects.

When I do setup 2), the file system will be different between repos. E.g. I will have public_code/Makefile in repo root but the file will be just Makefile in repo public_code. Will Mercurial still be able to synchronize changes between the repos? How could the workflow look like?

No, you cannot push and pull between the repositories if you create them like that. You can only push/pull between repositories when they originate from the same "mother" repository. Here it sounds like you'll create three unrelated repositories.


In a situation like this, you should evaluate carefully why you have svn:externals in Subversion and how they map to Mercurial subrepositories. They are not a 1–1 replacement for svn:externals. You should also look into tool support for subrepos — both in Mercurial itself and your Mercurial hosting, your continues build system, etc. I wrote part of the Mercurial subrepo code and as of Mercurial 2.0, there are still some sharp edges here and there.

In a nutshell, what subrepositories give you is a very tight coupling between subsystems. This is normally something to be avoided :-) We try hard to make our software systems loosely coupled since that gives us flexibility.

The main use case for subrepositories is a "build repository" where you track the precise versions of your components that you used in a given build. You cannot ask Mercurial to track the tip of a given branch in a subrepo, it will always track a given changeset in a given repository. This is what makes it possible to re-create a given checkout later: the .hgsubstate file tracks the precise changesets that were checked out in each subrepo.

So if your root repository is not used for development, but only for building releases, then subrepositories can in fact work great for you. The workflow will be something like

$ cd root
$ cd libs/shared_lib1
$ hg pull
$ hg update 2.0
$ cd ../..
$ make test && hg commit -m "Updated to sharedlib1 2.0"
$ hg tag 2.3

You then release version 2.3 of your software and Mercurial knows that it depends on version 2.0 of shared_lib1. You'll do this once in a while when the people responsible for the subcomponents tell you that they have a new release ready for you. Your CI server can of course do this nightly to see if the components work together!

Subrepositories work less well if the developers are working in root directly and if they make changes to the subcomponents as part of their work in root. That is an indication of a too tight coupling between the components: if main code depends on an exact changeset of a subcomponent, well then the subcomponent ought to be directly in the main code. Also, hg commit in the top-level repository will recurse and use the same commit message in the subrepos when ui.commitsubrepos=True. (The default was changed to False in Mercurial 2.0.) This is often not desired and when it does make sense, well then the subrepo to very tightly coupled and should be a part of the top-level repo.

So, to sum up: use subrepos if root is a "build repository". Otherwise, you should either inline the components in the top-level repository, or you should couple the pieces together more loosely by using something like Maven or similar to manage dependencies. These tools will normally let you say "please the latest version of root and all its dependencies" and then you can make a formal release when you're happy with the tests. These "snapshot" builds cannot be precisely reproduced, but that's also not needed — only the final releases need the strict and precise dependency tracking.

这篇关于调整svn:外部用法以迁移到Mercurial的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆