## page was renamed from subrepos #pragma section-numbers 2 #language zh ''Other Languages: [[Subrepository|En]],[[Frenchsubrepos|Fr]]'' = 子仓库 = 可自动化的从各种来源管理嵌套[[Repository|仓库]] <> == 简介 == 子仓库特性允许我们将不同的仓库成组的使用,允许统一的作为模块组进行克隆,检入,推送,下拉. 这一特性从 Mercurial 1.3 开始被内置支持了. 当前还有一些遗留命令来处理类子仓库事务,我们将统一这些命令,进行致性的子仓库感知. 对于SVN用户,子仓库的体验,非常接近运用 `svn:externals` 属性聲明的"卖方仓库". Mervurial 1.5 开始已经支持将SVN 作为子仓库使用. ^译注:万能的Python^ == 基础使用 == === 准备 === 啓用子仓库,至少需要两个版本仓库,主仓库和嵌套仓库: {{{ $ 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 }}} 如果你对默认分支进行更新时,也正是你得对子仓库进行更新之时. ==== 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]` === 检入 === 当我们对子仓库首次检入时,Mercurial 将创建一个子仓库版本状态的快照,以供主仓库判定是否进行联合检入; {{{ $ hg ci -m "test" committing subrepository nested }}} {i} 子仓库状态,储存在 ''`.hgsubstate`'' 文件中,由 Mercurial 自动进行管理. === 克隆 === 不论何时 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 知道如何循环处理. === 推送 === Mercurial 也自动尝试将所有嵌套仓库的变更推送上去. 只要在顶层仓库中聲明清楚所有包含的子仓库. === 下拉 === 但是,杯具是 `pull` ^下拉^命令 '''不是递归的!''' 这是因为 Mercurial 无法使用子仓库是否有变更,除非逐一进行 `pull -u`. === 在子仓库中同步 === 子仓库并不自动追踪所有源仓库的最新变化. 只是从顶层变更获取当前最新更动. 这样开发者在更新时总是可以获得兼容代码或是库的 ''一致变更集'' . 因而,更新子仓库是个标准操作,只要在对应的子仓库目录中执行 `hg up`, 同时这样也在顶层仓库中记录了最新变更组合. === 删除 === 从父仓库清除子仓库,必须从 ''`.hgsub`'' 删除对应聲明. 这时执行 `hg st` 询问仓库状态,子仓库树就将标识为 `未知`. 你就可以直接删除相关文件了. == 警告 == 因为这是全部的特性,有一些已知问题: * 一些命令需要 `-S` 开关来操作子仓库 * 很多命令并不理解子仓库 * 更新/合并,当前还无法彻底的清除子仓库的本地变更 * 对于子仓库还无法进行交叉重命名/移动 * 正常文件和子仓库的冲突还无法感知 * 子仓库的下拉总是被 延迟 直到进行更新 * `pull -r` 在子仓库中无法过滤版本 * push 命令也同样忽略 URL和版本过滤参数 * 还无法对子仓库传递一些命令参数,比如说:`-A` = 讨论 = ZoomQuiet :: * [[http://groups.google.com/group/kcpymaster/browse_thread/thread/f9c11451e5c494ac|Mercurial 作品集锦多仓库模式?]] * 实际上当前内置的 嵌套仓库支持,只是简单的将标准多仓库操作进行了自动化,还不能象 SVN 的卖方仓库那样灵活的进行仓库间的组合,比如说: * 在服务端,使用相对路径可以对本地仓库目录进行子仓库聲明:{{{ nested = ../foorepo }}} * 但是在本地,进行克隆时,先下载下来的主仓库会优先下载 `.hgsub` 聲明文件,并按照文件中的路径进行子仓库的克隆 * 于是就杯具的报告:`无法在 ../foorepo` 找到仓库! * 即使我们在 `.hg/hgrc` 以及 `.hgsub` 中进行了 URL 式的嵌套仓库聲明也依然难以成功: 1. `http://foo.exsample.org/main/foorepo` 是无法接受的! ~ Hg 仓库的发布无法只检出子目录 1. `http://foo.exsample.org/foorepo` 是不能识别的,因为单独发布的子仓库,不在 `.hgsub`聲明的嵌套关系中!