I have a git repository with several submodules (see an example). Its structure looks like this:
I--A--B <- main
\
C <- branch-c
- Commit A adds a
submodule-a
- Commit B adds a
submodule-b
- Commit C adds a
submodule-c
on branchbranch-c
When I clone the above repo using
git clone --recurse-submodules <URL>
only the submodule-a
and submodule-b
submodules get initialised and cloned.
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.
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
How do I check out (or switch to) branch branch-c
while automatically initialising all submodules?
CodePudding user response:
Your example repository is lacking a branch-c
, so it's not a complete MCVE, but it's a good start :)
When I clone the above repo using
git clone --recurse-submodules <URL>
only thesubmodule-a
andsubmodule-b
submodules get initialised and cloned.
Yes, this is the current behaviour of git clone --recurse-submodules
. The submodules are cloned and initialized using an invocation of git submodule update --init --recursive
during the checkout phase of git clone
, and as such, only submodules recorded in the default branch (or the branch specified using git clone -b <branch>
) are cloned and initialized.
When I then want to check out branch
branch-c
usinggit checkout branch-c
, the directory forsubmodule-c
gets created, but the submodule itself is not initialised. There is no indication in the command output that some additional steps are needed. Neithergit status
norgit diff
give any hint.
Yes, this is unfortunately still the default behaviour of Git. Submodules working trees are not checked out by default by git checkout <branch>
. git submodule status
(or just git submodule
) will show uninitialized submodules with a -
prefixed.
When instead I want to check out
branch-c
usinggit 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
This is a good reflex but unfortunately it does not work in that specific case and leads to this bad UX. git checkout --recurse-submodules <branch>
assumes that every submodule recorded in branch-c
are already initialized. Since that's not the case here, it errors out because it can't find the .git
directory of the submodule. The message could be clearer. What you have to do (the first time you switch to branch-c
after cloning your repository) is to check out branch-c
non-recursively, and then initialize the submodule:
git checkout branch-c
git submodule update --init --recursive
Then, you will be able to correctly switch between your branches with --recurse-submodules
:
git checkout --recurse-submodules main
git checkout --recurse-submodules branch-c
# etc
Note that you can set submodule.recurse
in your config to avoid having to use --recurse-submodules
all the time.