5

我有一个 mercurial 存储库,并且毫无问题地添加了 git subrepo ( hg 1.8 )。

问题是:这个 git subrepo 内部有另一个 git subrepository 并且它没有被拉取(它在 git 的 subrepo.gitmodules文件中),除非我git clone --recursive在我的 git subrepo 上做一个:这样做它可以工作。

问题:我hg pull在另一台机器的存储库中做了一个,它git subrepo拉了.gitmodules. .gitmodules 仅在我执行 .gitmodules 时才被拉入另一台机器git clone --recursive

有没有人有任何建议来处理这种情况?丑陋的解决方案是做一个git clone并简单地将所有文件(包括 git 元数据)添加到我的 mercurial 存储库中,而不像 subrepo 那样行事。

4

3 回答 3

3

我想最好的解决办法是修补 Mercurial 的 Git 子存储库支持以始终使用 Git 的递归选项(例如git clone --recursive,在克隆基于 Git 的子存储库时,git pull --recurse-submodules && git submodule update在拉取更新的基于 Git 的子存储库后等)。我知道 Git 开发人员特别选择不自动初始化子模块,因为他们想要支持的工作流程之一是“我永远不想看到任何子模块”,但也许“总是初始化所有子存储库”更适合默认的 Mercurial 操作模式(我不是 Mercurial 用户,所以我不知道默认的 Mercurial 样式是什么)。


在此之前,您可以通过将subrepo/.gitmodules条目转换为.hgsub条目来解决该问题。手动操作很容易,但如果它很重要,您可以将其自动化(用于git config.git/configand/or中提取路径和 URL .gitmodules)。如果您正在处理一个.gitmodules变化很大的文件,这可能没有吸引力(您必须非常勤奋地在.hgsub每次.gitmodules更改时同步)。

我用四个存储库对此进行了测试:

  • gitsub — 一个“叶子”存储库(没有 Git 子模块)
  • gitsuper — 一个 Git “超级项目”;
    gitsub/gitsub作为子模块
  • hgsuper2 — Mercurial“超级项目”;
    gitsuper/gitsuper作为子存储库,
    gitsuper/gitsubgitsub作为子存储库。
  • hgsuper2-clone — 一个克隆的 Mercurial “超级项目”;
    gitsuper/gitsuper作为子存储库,
    gitsuper/gitsubgitsub作为子存储库。

我像这样构建和测试它们:

  1. 创建gitsub。添加并提交一些内容。
  2. 创建gitsuper
    1. 添加一些内容。
    2. git submodule add url-of-gitsub gitsub && git submodule init
    3. git commit -m 'added gitsub'
  3. 创建hgsuper2
    1. 添加一些内容。
    2. git clone --recursive url-of-gitsuper gitsuper
    3. echo 'gitsuper = [git]url-of-gitsuper' >> .hgsub
    4. echo 'gitsuper/gitsub = [git]url-of-gitsub' >> .hgsub
      这最后两个步骤可以从 和 的位中gitsuper/.git/config自动化gitsuper/.gitmodules
    5. hg add .hgsub && hg commit -m 'added Git subrepositories'
  4. hgsuper2克隆hgsuper2-clone。它在和 中获取适当的内容。
    gitsuper/gitsuper/gitsub/
  5. 更新并将新内容提交到gitsub
  6. 更新gitsuper
    1. 添加或更改一些内容并将其暂存。
    2. (cd gitsub && git pull origin master)
    3. git add gitsub && git commit -m 'updated gitsuper content (also gitsub)'
  7. hgsuper2中,从 Git 存储库中提取更改。
    1. (cd gitsuper && git pull --recurse-submodules && git submodule update)
      gitsuper/和中 的内容gitsuper/gitsub/由拉取更新。
    2. hg commit -m 'updated gitsuper (and its contents)'
  8. 拉入hgsuper2-clone
    1. hg pull -u
      来自 Git 的内容已更新。

我的测试有效(使用 Mercurial 1.8.1 和 Git 1.7.4.1),但我注意到一个错误。Mercurial 创建并签出一个奇怪命名的 Git 分支(origin/master(ie refs/heads/origin/master) 而不是使用分离的 HEAD(就像 Git 对其子模块所做的那样)或仅使用master(ie refs/heads/master))。有时它似乎也有点卡住,导致如下错误:

fatal: git checkout: branch origin/master already exists
abort: git checkout error 128 in gitsuper

我通过进入有问题的 Git 存储库(基于 Git 的 Mercurial 子存​​储库)并使用git checkout HEAD~0 && git branch -D origin/master(第一个分离 HEAD 并且(更重要的是)移出分支以便可以通过下一个命令删除它)来解决这个问题)。只要您在 Git 存储库中没有任何本地更改更改,此解决方法是完全安全的。

另一个小问题是,在由 Mercurial 创建的 Git 超级存储库中发出 Git 子模块命令之前,您需要运行git submodule init让 Git 知道它的子模块(子模块被克隆到正确的位置,但它们是由 Mercurial 建立的,所以)中没有它们的条目.git/config

同样,如果您计划从基于 Git 的 Mercurial 子存​​储库中对 Git 管理的内容进行创作更改,那么您应该小心始终添加任何 Git 子模块、提交和推送,然后再提交到 Mercurial “超级项目”。否则,您最终可能会遇到 Mercurial 使用gitsupergitsub的一种组合而gitsuper本身引用不同版本的gitsub的情况。换句话说,由于您将绕过 Git 的子模块代码(通过将 Git 子模块作为 Mercurial 子存​​储库进行管理),因此您需要小心保持 Git 的子模块视图与 Mercurial 的视图同步。

于 2011-04-03T08:45:00.707 回答
2

对于未来的潜伏者。您实际上可能会使用Mercurial 的Hg-Git 插件来自动检索 git 子模块:

  1. 通过 apt/pacman/pip/... 安装扩展并在你的~/.hgrc
  2. 通过导航到您的项目目录或只是一些虚拟存储库hg init test && cd test
  3. 克隆您的 git 依赖项(它也有自己的子模块)并将其固定到您想要的提交中:hg clone https://github.com/user/libawesome.git && (cd libawesome && hg up release)
  4. 将其保存.hgsub为任何其他hg 子存储库并提交更改:echo "libawesome = https://github.com/user/libawesome.git" >> .hgsub && hg add .hgsub && hg ci -m "git subrepository added;"
  5. 您现在可以验证 git 依赖项是否被传递克隆:(cd .. && hg clone test test2)
于 2017-12-12T21:47:32.977 回答
0

Git 并不真正“喜欢”子项目。我环顾四周,似乎http://git.rsbx.net/Notes/Git_Subprojects.txt可能包含您正在寻找的信息?

于 2011-04-02T21:19:34.073 回答