如何在递归初始化子模块时切换到另一个分支

How to switch to another branch while recursively initing submodules

我有一个包含多个子模块 (see an example) 的 git 存储库。它的结构如下所示:

I--A--B <- main
       \
        C <- branch-c

当我使用 git clone --recurse-submodules <URL> 只有 submodule-asubmodule-b 子模块被初始化和克隆。

当我想使用 git checkout branch-c 检查分支 branch-c 时,submodule-c 的目录被创建,但子模块本身没有被初始化。命令输出中没有指示需要一些额外的步骤。 git statusgit diff 都没有给出任何提示。

当我想使用 git checkout --recurse-submodules branch-c 查看 branch-c 时,我得到一个错误:

fatal: not a git repository: ../../.git/modules/subrepos/subrepo-c
fatal: could not reset submodule index

如何在自动初始化所​​有子模块的同时检出(或切换到)分支 branch-c

您的示例存储库缺少 branch-c,因此它不是完整的 MCVE,但它是一个好的开始:)

When I clone the above repo using git clone --recurse-submodules <URL> only the submodule-a and submodule-b submodules get initialised and cloned.

是的,这是git clone --recurse-submodules的当前行为。使用 git submodule update --init --recursive during the checkout phase of git clone 的调用克隆和初始化子模块,因此,仅记录在默认分支(或使用 git clone -b <branch> 指定的分支)中的子模块被克隆和初始化。

When I then want to check out branch branch-c using git checkout branch-c, the directory for submodule-c gets created, but the submodule itself is not initialised. There is no indication in the command output that some additional steps are needed. Neither git status nor git diff give any hint.

是的,不幸的是,这仍然是 Git 的默认行为。 git checkout <branch> 默认不检查子模块工作树。 git submodule status(或仅 git submodule)将显示带有 - 前缀的未初始化子模块。

When instead I want to check out branch-c using git checkout --recurse-submodules branch-c I get an error:

fatal: not a git repository: ../../.git/modules/subrepos/subrepo-c
fatal: could not reset submodule index

这是一个很好的反应,但不幸的是,它在特定情况下不起作用并导致这种糟糕的用户体验。 git checkout --recurse-submodules <branch> 假设 branch-c 中记录的每个子模块都已经初始化。由于这里不是这种情况,它会出错,因为它找不到子模块的 .git 目录。信息可能更清楚。你要做的(克隆你的存储库后第一次切换到 branch-c)是检查 branch-c non-recursively,然后初始化子模块:

git checkout branch-c
git submodule update --init --recursive

然后,您将能够使用 --recurse-submodules:

在您的分支之间正确切换
git checkout --recurse-submodules main
git checkout --recurse-submodules branch-c
# etc

请注意,您可以在配置中设置 submodule.recurse 以避免必须一直使用 --recurse-submodules