使用在 Mercurial 存储库中有另一个 git subrepo 的 git subrepo,这可能吗?
我有一个 Mercurial 存储库,并且毫无问题地添加了 git subrepo (hg 1.8)。
问题是:这个 git subrepo 内部有另一个 git subrepository 并且它没有被拉取(它位于 git 的 subrepo .gitmodules
文件中),除非我执行 git clone --recursive< /code> 在我的 git subrepo 上:这样做是有效的。
问题:我在另一台机器上的存储库中执行了 hg pull
,它提取了 git subrepo
,但它没有提取 .gitmodules
>。当我执行 git clone --recursive 时,.gitmodules 仅被拉入另一台机器。
有人对处理这种情况有什么建议吗? 丑陋的解决方案是进行git克隆
并简单地将所有文件(包括git元数据)添加到我的mercurial存储库中,而不像子存储库一样。
I have a mercurial repository, and have added without problems a git subrepo (hg 1.8).
Problem is: this git subrepo has ANOTHER git subrepository inside itself and it isn't being pulled (it's in the git's subrepo .gitmodules
file), unless I do a git clone --recursive
on my git subrepo: doing this way it works.
The problem: I do a hg pull
in my repository in another machine, it pulls the git subrepo
, but it doesn't pull the .gitmodules
. The .gitmodules was only pulled in the other machine when I did a git clone --recursive
.
Does anybody has any suggestions to handle this situation? The ugly solution is to do a git clone
and simply add all the files (including git metadata) to my mercurial repository, without acting like a subrepo.
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(3)
我认为最好的解决方法是修补 Mercurial 的 Git 子存储库支持,以始终使用 Git 的递归选项(例如,在克隆基于 Git 的子存储库时,使用 git pull --recurse- submodules && git submodule update 在拉取更新的基于 Git 的子存储库后等)。我知道 Git 开发人员特意选择不自动初始化子模块,因为他们想要支持的工作流程之一是“我永远不想看到任何子模块”,但也许“始终初始化所有子存储库”更适合默认的 Mercurial 操作模式(我不是一个很好的 Mercurial 用户,所以我不太清楚默认的 Mercurial 风格是什么)。
在此之前,您也许可以通过将
subrepo/.gitmodules
条目转换为.hgsub
条目来解决该问题。手动操作很容易,但如果它很重要,您可能可以将其自动化(使用 git config 从 .git/config 和/或.git/config 中提取路径和 URL代码>.gitmodules
)。如果您正在处理变化很大的.gitmodules
文件,这可能没有吸引力(您必须非常勤奋地每次.gitmodules< 同步
.hgsub
/代码> 已更改)。我用四个存储库对此进行了测试:
gitsub/
是 gitsub 作为子模块gitsuper/
是 gitsuper 作为子存储库,gitsuper/gitsub
是 gitsub 作为子存储库。gitsuper/
是 gitsuper 作为子存储库,gitsuper/gitsub
是 gitsub 作为子存储库。我像这样构建和测试它们:
git 子模块 add url-of-gitsub gitsub && git 子模块初始化
git commit -m '添加了 gitsub'
git clone --recursive url-of-gitsuper gitsuper
echo 'gitsuper = [git]url-of-gitsuper'>>> .hgsub
echo 'gitsuper/gitsub = [git]url-of-gitsub'>>> .hgsub
最后两个步骤可以通过
gitsuper/.git/config
和gitsuper/.gitmodules
自动化。hg add .hgsub && hg commit -m '添加了 Git 子存储库'
它获取
gitsuper/
和gitsuper/gitsub/
中的适当内容。(cd gitsub && git pull origin master)
git add gitsub && git commit -m '更新了 gitsuper 内容(也是 gitsub)'
(cd gitsuper && git pull --recurse-submodules && git 子模块更新)
gitsuper/
和gitsuper/gitsub/
中的内容通过拉取进行更新。hg commit -m '更新了 gitsuper(及其内容)'
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
))。有时它似乎也有点卡住,导致这样的错误:我通过进入有问题的 Git 存储库(基于 Git 的 Mercurial 子存储库)并使用 git checkout HEAD 删除分支来解决这个问题~ 0 && gitbranch -D origin/master (第一个分离 HEAD 并且(更重要的是)移出分支,以便下一个命令可以将其删除)。只要您在 Git 存储库中没有任何本地更改,此解决方法就是完全安全的。
另一个小问题是,在 Mercurial 创建的 Git 超级存储库中发出 Git 子模块命令之前,您需要运行 git submodule init 来让 Git 了解其子模块(子模块被克隆到右侧)的地方,但它们是由 Mercurial 建立的,因此
.git/config
中没有它们的条目)。同样,如果您计划从基于 Git 的 Mercurial 子存储库内部对 Git 管理的内容进行创作更改,那么您应该小心,在在 Mercurial 中提交之前,始终从 Git 子存储库添加任何 Git 子模块、提交和推送。 “超级项目”。否则,您可能最终会遇到 Mercurial 使用 gitsuper 和 gitsub 的组合,而 gitsuper 本身引用 gitsuper 的不同版本的情况>gitsub。换句话说,由于您将绕过 Git 的子模块代码(通过将 Git 子模块作为 Mercurial 子存储库进行管理),因此您需要小心保持 Git 的子模块视图与 Mercurial 的视图同步。
I suppose the best fix would be to patch Mercurial’s Git subrepository support to always use Git’s recursive options (e.g.
git clone --recursive
when cloning a Git-based subrepository,git pull --recurse-submodules && git submodule update
after pulling an updated Git-based subrepository, etc.). I know that the Git developers specifically chose to not automatically initialize submodules because one of the workflows they want to support is “I never want to see any of the the submodules”, but maybe “always initialize all subrepositories” is a better match to the default Mercurial mode of operation (I am not much of a Mercurial user, so I do not have a good idea of what the default Mercurial style would be).Until that happens, you might be able to work around the problem by translating the
subrepo/.gitmodules
entries into.hgsub
entries. It is easy to do manually, but you could probably automate it if it was important (usegit config
to extract the paths and URLs from.git/config
and/or.gitmodules
). This may be unappealing if you are dealing with a.gitmodules
file that changes much (you would have to be very diligent about synchronizing.hgsub
each time.gitmodules
changed).I tested this with four repositories:
gitsub/
is gitsub as a submodulegitsuper/
is gitsuper as a subrepository,gitsuper/gitsub
is gitsub as a subrepository.gitsuper/
is gitsuper as a subrepository,gitsuper/gitsub
is gitsub as a subrepository.I built and tested them like this:
git submodule add url-of-gitsub gitsub && git submodule init
git commit -m 'added gitsub'
git clone --recursive url-of-gitsuper gitsuper
echo 'gitsuper = [git]url-of-gitsuper' >> .hgsub
echo 'gitsuper/gitsub = [git]url-of-gitsub' >> .hgsub
These last two steps could be automated from bits of
gitsuper/.git/config
andgitsuper/.gitmodules
.hg add .hgsub && hg commit -m 'added Git subrepositories'
It gets the appropriate contents in
gitsuper/
andgitsuper/gitsub/
.(cd gitsub && git pull origin master)
git add gitsub && git commit -m 'updated gitsuper content (also gitsub)'
(cd gitsuper && git pull --recurse-submodules && git submodule update)
The content in
gitsuper/
andgitsuper/gitsub/
is updated by the pull.hg commit -m 'updated gitsuper (and its contents)'
hg pull -u
The content from Git has been updated.
My tests worked (using Mercurial 1.8.1 and Git 1.7.4.1), but I noticed one bug. Mercurial creates and checks out an oddly named Git branch (
origin/master
(i.e.refs/heads/origin/master
) instead of using a detached HEAD (like Git does with its submodules) or just usingmaster
(i.e.refs/heads/master
)). It also seems to get a bit wedged at times, resulting in errors like this:I worked around the problem by going into the Git repository in question (the Git-based Mercurial subrepository) and deleting the branch with
git checkout HEAD~0 && git branch -D origin/master
(the first detaches HEAD and (more importantly) moves off of the branch so it can be deleted by the next command). This workaround is completely safe as long as you do not have any local changes changes in the Git repository.Another small problem is that you will need to run
git submodule init
to let Git know about its submodules before issuing Git submodule commands in a Git super repository that was created by Mercurial (the submodules were cloned to the right places, but they were established by Mercurial, so there are no entries for them in.git/config
).Similarly, if you plan on authoring changes to the content that is managed by Git from inside the Git-based Mercurial subrepository, then you should be careful to always add any Git submodules, commit, and push from the Git subrepositories before committing in the Mercurial “superproject”. Otherwise, you might end up with a situation where Mercurial uses one combination of gitsuper and gitsub while gitsuper itself refers to a different version of gitsub. In other words, since you will be bypassing Git’s submodule code (by managing the Git submodules as Mercurial subrepositories), you will need to be careful to keep Git’s view of the submodules synchronized with that of Mercurial.
对于未来的潜伏者。您实际上可能会使用 Mercurial 的 Hg-Git 插件 来自动检索 git 子模块:
~/.hgrc
中激活它hg init test && 导航到您的项目目录或只是一些虚拟存储库cd test
hg clone https://github.com/user/libawesome.git && (cd libawesome && hg up release)
.hgsub
中,作为任何其他 hg 子存储库 并提交更改:echo "libawesome = https://github.com/user/libawesome.git">> .hgsub && hg 添加 .hgsub && hg ci -m "git subrepository added;"
(cd .. && hg clone test test2)
For future lurkers. You might actually use Hg-Git plugin for Mercurial to get automatic retrieval of git submodules:
~/.hgrc
hg init test && cd test
hg clone https://github.com/user/libawesome.git && (cd libawesome && hg up release)
.hgsub
as any other hg subrepository and commit changes:echo "libawesome = https://github.com/user/libawesome.git" >> .hgsub && hg add .hgsub && hg ci -m "git subrepository added;"
(cd .. && hg clone test test2)
Git 并不真正“喜欢”子项目。我环顾四周,似乎 http://git.rsbx.net/Notes/ Git_Subprojects.txt 可能包含您要查找的信息?
Git doesn't really "like" subprojects. I did a little looking around, and it seems like http://git.rsbx.net/Notes/Git_Subprojects.txt might contain the information you're looking for?