在一个Mercurial存储库中使用具有另一个Git子存储库的Git子存储库,这是否可能?

5
我有一个mercurial存储库,并且已经成功添加了一个git子存储库(hg 1.8)。
问题是:这个git子存储库内部还有另一个git子存储库,除非我在git子存储库上执行git clone --recursive,否则它不会被拉取(它在git的子存储库.gitmodules文件中):以这种方式进行操作可以解决问题。
问题是:当我在另一台机器上的存储库中执行hg pull时,它会拉取git subrepo,但它不会拉取.gitmodules。只有当我执行git clone --recursive时,.gitmodules才会在其他计算机上被拉取。
有人有任何建议来处理这种情况吗?“丑陋”的解决方案是执行git clone并将所有文件(包括git元数据)添加到我的mercurial存储库中,而不像子存储库那样操作。
3个回答

3
我认为最好的解决方法是修补Mercurial的Git子存储库支持,使其始终使用Git的递归选项(例如,当克隆基于Git的子存储库时使用git clone --recursive,在拉取更新的基于Git的子存储库后使用git pull --recurse-submodules && git submodule update等)。我知道Git开发人员明确选择不自动初始化子模块之一的工作流程,因为他们想要支持的工作流程之一是“我永远不想看到任何子模块”,但也许“始终初始化所有子存储库”更符合默认Mercurial操作模式(我不是很了解Mercurial用户,所以我对默认的Mercurial风格没有什么概念)。
在此之前,您可能可以通过将subrepo/.gitmodules条目转换为.hgsub条目来解决问题。手动很容易做到,但如果重要的话,您可能可以通过使用git config.git/config和/或.gitmodules中提取路径和URL来自动执行它。如果您正在处理经常更改的.gitmodules文件,则可能会感到不舒服(每次更改.gitmodules都必须非常努力地同步.hgsub)。
我使用了四个存储库进行了测试:
  • 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/configgitsuper/.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,即refs/heads/origin/master),而不是使用分离的HEAD(就像Git子模块一样)或仅使用master(即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仓库中进行任何本地更改,这个解决方法是完全安全的。
另一个小问题是,在发出Git子模块命令之前,您需要运行git submodule init让Git知道其子模块。如果您在由Mercurial创建的Git超级仓库中操作Git子模块,则子模块已经克隆到正确的位置,但是它们是由Mercurial建立的,因此在.git/config中没有相应的条目。
同样,如果您计划从基于Git的Mercurial子仓库内部管理Git内容的更改,则应该注意在提交Mercurial“超级项目”之前始终添加任何Git子模块,并从Git子仓库中提交和推送。否则,您可能会遇到这样一种情况:Mercurial使用gitsupergitsub的某种组合,而gitsuper本身引用了不同版本的gitsub。换句话说,由于您将通过将Git子模块作为Mercurial子仓库管理来绕过Git的子模块代码,因此您需要小心地保持Git对子模块的视图与Mercurial的视图同步。

非常棒的答案。赏金归你了。感谢你的所有努力。我将测试这些解决方法,也许会在Mercurial的代码和邮件列表中搜索有关修补此行为的信息。 - Somebody still uses you MS-DOS
你的回答当时确实很棒,但是我只是放弃了这一切的疯狂。 :) - Somebody still uses you MS-DOS

2
对于未来的读者。你可以使用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. 像任何其他hg子存储库一样将其保存在.hgsub中并提交更改: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)

0

这份文档相当古老。很可能是在 Git 1.5.3(2007 年 9 月)获得子模块支持之前编写的。它使用的“虚线命令”(git-clone 而不是 git clone)已经在 Git 1.5.4(2008 年 2 月)中被弃用,并在 Git 1.6(2008 年 8 月)中从正常 PATH 中移除。我不确定这份文件应该如何帮助提问者。它是否应该提供一些手动管理子项目的想法?在我看来,这主要是一个 Mercurial 问题(如何让它自动使用基于 Git 的子存储库中的.gitmodules文件)。 - Chris Johnsen
@Chris Johnsen:确切地说,Mercurial可以将git仓库作为子仓库,但是当这些作为hg子仓库的git仓库本身具有git子仓库(在.gitmodules文件中)时,.gitmodules中的此仓库不会被克隆。我必须手动克隆git子仓库。 - Somebody still uses you MS-DOS

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接