假设我有带有子模块的 git repo。
假设其中一个子模块有分支
Br1
(当前已签出)和分支 Br2
。
Br1
已提交:A->BBr1
已提交:ABr2
已提交:A->BBr2
已提交:A->B换句话说,本地
Br1
领先:
git status
On branch v1.1.0_with_fixes
Your branch is ahead of 'origin/v1.1.0_with_fixes' by 1 commit.
(use "git push" to publish your local commits)
nothing to commit, working tree clean
但是其本地 SHA 存在于另一个分支的远程中。
如果我调用
git push--recurse-submodules=on-demand
(从父存储库),什么(如果有)被推送到哪里?
附注
实验表明根本没有任何东西被推动......这令人困惑......
使用
--recurse-submodules=on-demand
,Git 检查超级项目中记录的新子模块提交是否可以从子模块中的至少一个远程跟踪分支到达,如果不能则推送它们。这可以 [*] 解释为什么在您的情况下没有推送任何内容,因为远程分支 Br2
指向 B.
此行为在 doc 中没有得到很好的描述,其中指出:
如果使用 check,Git 将验证要推送的修订版本中更改的所有子模块提交在子模块的至少一个远程上可用。如果缺少任何提交,推送将中止并以非零状态退出。如果使用on-demand,则将推送要推送的修订版本中更改的所有子模块。
正如我在上面所写的,事实上,只有当子模块中的至少一个远程跟踪分支无法访问它们时,它们才会被推送。这是在
submodule_needs_pushing
中实现的,从 find_unpushed_submodules
调用,由 push_unpushed_submodules
使用,实现 on-demand
(参见 transport_push
)。
[*] 我写“可以”,因为从您的帖子中不清楚当您调用
git push --recurse-submodules=on-demand
时哪个提交记录在超级项目中。如果子模块处于“已修改”状态,则 --recurse-submodules=on-demand
不执行任何操作。只有当记录的子模块提交被更改在被推送的超级项目提交中时,它才会生效。
因此,问题第一部分(推送什么(如果有))的答案是:Git 确定一组子模块提交,我们将它们称为“新子模块提交”,记录在正在推送的超级项目分支中;如果子模块中的远程跟踪分支无法访问这些“新子模块提交”,则会推送它们。
请注意,Git 确定要检查的子模块提交集的方式是检查所有更改正在推送的超级项目分支中的子模块的提交,这些提交尚未通过超级项目中的远程跟踪分支到达(请参阅) find_unpushed_submodules
--recurse-submodules=on-demand
,因此很可能子模块提交也已经被推送了。
现在对于问题的另一部分(新的子模块提交推送到哪里),这更容易:如果有要推送的子模块提交,它们会被推送到子模块中与超级项目分支同名的分支被推送到与被推送到的子模块远程同名的远程06bf4ad1db(push:使用 --recurse-submodules 传播远程和 refspec,2017-04-05)进入 Git 2.13 以来就是这种情况。仅当在 git push
调用中将 URL 或文件系统路径指定为远程时,才会使用子模块的默认远程和 refspec。