子仓库
可自动化的从各种来源管理嵌套仓库
1. 简介
子仓库特性允许我们将不同的仓库成组的使用,允许统一的作为模块组进行克隆,检入,推送,下拉.
这一特性从 Mercurial 1.3 开始被内置支持了. 当前还有一些遗留命令来处理类子仓库事务,我们将统一这些命令,进行致性的子仓库感知.
对于SVN用户,子仓库的体验,非常接近运用 svn:externals 属性聲明的"卖方仓库". Mervurial 1.5 开始已经支持将SVN 作为子仓库使用. 译注:万能的Python
2. 基础使用
2.1. 准备
啓用子仓库,至少需要两个版本仓库,主仓库和嵌套仓库:
$ hg init main $ cd main $ hg init nested $ echo test > nested/foo $ hg -R nested add nested/foo $ hg -R nested ci -m '初始化子仓库'
我们要在特殊文件:.hgsub 中创建记录,聲明嵌套仓库. 注意,这里使用 .ini 类似的参数聲明形式,等号前的 nested 是指我们将嵌套仓库安装到的目录; 后面的 nested 是子仓库真正的访问URI, 这里因为是就地创建的,所以和安装目录相同; 意思就是:任何人只要找到我们的主仓库,就可以根据这里的路径访问到子仓库
$ echo nested = nested > .hgsub $ hg add .hgsub
注意,嵌套仓库必须在 .hgsub 中聲明,才能和主仓库形成嵌套关系; 否则,你得手工的逐一对"嵌套"仓库进行克隆下拉.即,形式上嵌套,但是仓库间不认识
$ echo nested = https://example.com/nested/repo/path > .hgsub $ hg add .hgsub $ hg clone https://example.com/nested/repo/path nested
如果你对默认分支进行更新时,也正是你得对子仓库进行更新之时.
2.1.1. SVN 子仓库
从1.5版本之后,Mercurial 支持其它版本系统的子仓库. 比如说,你将一个SVN 仓库装配成子仓库:
$ echo 'nested = [svn]https://example.com/nested/trunk/path' >.hgsub $ hg add .hgsub $ svn co https://example.com/nested/trunk/path nested
实际上, Mercurial 将没有 [<仓库类型>] 前导的聲明,视作使用了 [hg]
2.2. 检入
当我们对子仓库首次检入时,Mercurial 将创建一个子仓库版本状态的快照,以供主仓库判定是否进行联合检入;
$ hg ci -m "test" committing subrepository nested
子仓库状态,储存在 .hgsubstate 文件中,由 Mercurial 自动进行管理.
2.3. 克隆
不论何时 Mercurial 都将试图更新所有嵌套仓库,到合适的状态:
$ cd .. $ hg clone main main2 updating working directory pulling subrepo nested requesting all changes adding changesets adding manifests adding file changes added 1 changesets with 1 changes to 1 files 2 files updated, 0 files merged, 0 files removed, 0 files unresolved $ cat main2/nested/foo test
子仓库也包含专用的版本数据库,Mercurial 知道如何循环处理.
2.4. 推送
Mercurial 也自动尝试将所有嵌套仓库的变更推送上去. 只要在顶层仓库中聲明清楚所有包含的子仓库.
2.5. 下拉
但是,杯具是 pull 下拉命令 不是递归的!
这是因为 Mercurial 无法使用子仓库是否有变更,除非逐一进行 pull -u.
2.6. 在子仓库中同步
子仓库并不自动追踪所有源仓库的最新变化. 只是从顶层变更获取当前最新更动. 这样开发者在更新时总是可以获得兼容代码或是库的 一致变更集 .
因而,更新子仓库是个标准操作,只要在对应的子仓库目录中执行 hg up, 同时这样也在顶层仓库中记录了最新变更组合.
2.7. 删除
从父仓库清除子仓库,必须从 .hgsub 删除对应聲明. 这时执行 hg st 询问仓库状态,子仓库树就将标识为 未知. 你就可以直接删除相关文件了.
3. 警告
因为这是全部的特性,有一些已知问题:
一些命令需要 -S 开关来操作子仓库
- 很多命令并不理解子仓库
- 更新/合并,当前还无法彻底的清除子仓库的本地变更
- 对于子仓库还无法进行交叉重命名/移动
- 正常文件和子仓库的冲突还无法感知
- 子仓库的下拉总是被 延迟 直到进行更新
pull -r 在子仓库中无法过滤版本
- push 命令也同样忽略 URL和版本过滤参数
还无法对子仓库传递一些命令参数,比如说:-A
讨论
ZoomQuiet ::
- 实际上当前内置的 嵌套仓库支持,只是简单的将标准多仓库操作进行了自动化,还不能象 SVN 的卖方仓库那样灵活的进行仓库间的组合,比如说:
在服务端,使用相对路径可以对本地仓库目录进行子仓库聲明:
nested = ../foorepo
但是在本地,进行克隆时,先下载下来的主仓库会优先下载 .hgsub 聲明文件,并按照文件中的路径进行子仓库的克隆
于是就杯具的报告:无法在 ../foorepo 找到仓库!
即使我们在 .hg/hgrc 以及 .hgsub 中进行了 URL 式的嵌套仓库聲明也依然难以成功:
http://foo.exsample.org/main/foorepo 是无法接受的! ~ Hg 仓库的发布无法只检出子目录
http://foo.exsample.org/foorepo 是不能识别的,因为单独发布的子仓库,不在 .hgsub聲明的嵌套关系中!