Nested submodule checkout
- From
- Damien Robert <damien.olivier.robert@gmail.com>
- Date
- Feb 14, 2020, 22:42 UTC
- Message-ID
- <20200214224242.knmzkwx7ls4sote7@doriath>
Dear git developers,
I stumbled into this situation from which it was a bit painful to recover:
-> test script:
mkdir ploum
cd ploum
git init
echo 'foo' > foo
git add foo
git commit -m foo
git branch nosubmodules mkdir plam
cd plam
git init
echo 'bar' > bar
git add bar
git commit -m bar mkdir plim
cd plim
git init
echo 'baz' > baz
git add baz
git commit -m baz cd ..
git submodule add ./plim
git commit -am 'Add submodule plim' cd ..
git submodule add ./plam
git commit -am 'Add submodule plam' git checkout nosubmodules
git checkout --recurse-submodules master-> The result is as follow:
Initialized empty Git repository in /data/dams/var/tmp/ploum/.git/ [master (root-commit) ec7c09a] foo 1 file changed, 1 insertion(+) create mode 100644 foo Branch 'nosubmodules' set up to track local branch 'master'. Initialized empty Git repository in /data/dams/var/tmp/ploum/plam/.git/ [master (root-commit) 35e6696] bar 1 file changed, 1 insertion(+) create mode 100644 bar Initialized empty Git repository in /data/dams/var/tmp/ploum/plam/plim/.git/ [master (root-commit) b4712c1] baz 1 file changed, 1 insertion(+) create mode 100644 baz Adding existing repo at 'plim' to the index [master 989c11d] Add submodule plim 2 files changed, 4 insertions(+) create mode 100644 .gitmodules create mode 160000 plim Adding existing repo at 'plam' to the index [master 5b34041] Add submodule plam 2 files changed, 4 insertions(+) create mode 100644 .gitmodules create mode 160000 plam Migrating git directory of 'plam' from '/data/dams/var/tmp/ploum/plam/.git' to '/data/dams/var/tmp/ploum/.git/modules/plam' Migrating git directory of 'plam/plim' from '/data/dams/var/tmp/ploum/plam/plim/.git' to '/data/dams/var/tmp/ploum/.git/modules/plam/modules/plim' Switched to branch 'nosubmodules' Your branch is behind 'master' by 1 commit, and can be fast-forwarded. (use "git pull" to update your local branch) fatal: exec '--super-prefix=plam/plim/': cd to 'plim' failed: No such file or directory error: Submodule 'plim' could not be updated. error: Submodule 'plam/plim' cannot checkout new HEAD. error: Submodule 'plam' could not be updated. M plam Switched to branch 'master'
As you can see, the nested plim submodules could not be recreated since the folder does not exists yet in the 'nosubmodules' branch. This makes the 'plam' submodule update fails, and in the following state
Unstaged changes after reset: D .gitmodules D bar D plim
-> To recover
In the folder plam, do a `git reset` followed by a `git reset --hard` (`git reset --hard` directly does not work: fatal: exec '--super-prefix=plim/': cd to 'plim' failed: No such file or directory)
Indeed the first reset, which puts .gitmodules back in the index, is what allows to do the `git submodule update` implied by `git reset --hard`. Since (from what I understand) the path is only read from .gitmodules and not from the .git/config (where there are only the submodules name which are distinct from the path), this explain the failures observed.
Note that I wasn't able to reproduce in this small examples, but when trying to repair I also add some strange errors of the form '.git is not a git directory' (where .git was a pseudo symlink gitdir: ../.git/modules/plam).
-> Question
My usage is probably non standard (I have quite a lot of nested submodules), so I had a hard time to recover from this checkout. Is there a better way? Would it be possible to make nested submodules checkout of this form work out of the box?
Thanks! Damien Robert