After pulling, I would like to initialize all new submodules recursively with a single command.
The issue with using git submodule update --init --recursive
is that it also resets which commit my pre-existing submodules are pointing to.
CodePudding user response:
git submodule update --init --recursive
is indeed the right command to use to initialize all submodules, recursively. The submodules repositories will be cloned, and the commit recorded in the superproject will be checked out.
This is correctly documented in git-submodule(1)
:
Update the registered submodules to match what the superproject expects by cloning missing submodules, fetching missing commits in submodules and updating the working tree of the submodules. The "updating" can be done in several ways depending on command line options and the value of
submodule.<name>.update
configuration variable. The command line option takes precedence over the configuration variable. If neither is given, a checkout is performed. [...]
checkout
: the commit recorded in the superproject will be checked out in the submodule on a detached HEAD.[...]
If the submodule is not yet initialized, and you just want to use the setting as stored in
.gitmodules
, you can automatically initialize the submodule with the--init
option.If
--recursive
is specified, this command will recurse into the registered submodules, and update any nested submodules within.
Note that you can get the same behaviour by simply using git clone --recurse-submodules
.
CodePudding user response:
This is far enough off the beaten path that I think you're going to have to script it. Almost all Git commands started out as scripts and could still be done that way.
If you always keep all submodules active then git submodule foreach --recursive
is your starting point, but if you're selective about which submodules get checked out at all you're going to have to do more than just
git submodule foreach --recursive -q 'echo git -C $PWD checkout `git rev-parse @`'
(which is actually an example in the git submodule
docs) and run the checkouts that prints to restore what you care about after the recursive update does too much.
CodePudding user response:
Now you changed your question completely and you are asking (emphasis mine):
After pulling, I would like to initialize all new submodules recursively with a single command.
The issue with using
git submodule update --init --recursive
is that it also resets which commit my pre-existing submodules are pointing to.
It would be nice to have more details here, including an MCVE (in the case of Git questions, that usually means the complete set of Git commands to run, starting from git init
/git clone
). If not your readers are left to guess your exact situation (and with submodules, there are a lot of possibilities).
To initialize new submodules only, you first would have to find out if there are any new submodules that were brought by the git pull
you did. Something like the following should list submodules (grep 160000
) that have been added (--diff-filter=A
) since the commit you were on before pulling (ORIG_HEAD..
):
git log --format=%h ORIG_HEAD.. --summary --diff-filter=A | \grep 160000 | awk '{print $4}'
You could then use git submodule update
with this list of submodules to only initialize these ones:
git submodule update --init --recursive $(git log --format=%h ORIG_HEAD.. --summary --diff-filter=A | \grep 160000 | awk '{print $4}' | tr \\n ' ')
Note that it's not clear from your question in what state are your pre-existing submodules, the ones that you want to avoid changing. Are they "modified" (i.e. you checked out a different commit in the submodule, but did not run git add
in the superproject yet), "added" (i.e. you checked out a different commit in the submodule, ran git add
in the superproject, but did not commit that change in the superproject yet) or if on the contrary your working directory is completely clean, but you did commit submodule changes since your last pull. Depending on that and what you want the end result to look like, simply running git submodule update --init --recursive --merge
or git submodule update --init --recursive --rebase
might fill your needs...