How to checkout old git commit including all submodules recursively?

How to checkout old git commit including all submodules recursively?

I have a git repo with multiple submodules. One of those submodules has multiple submodules of it’s own. All I’m looking to do is check out an old commit on the master repo and have it checkout the appropriate commits from all submodules to get the correct state of the code at that time.
I know that git contains the information necessary as the ls-tree command can tell me which commit each submodule was on. However, I have to manually check out each one, which is painfully time consuming.
I’m looking for something like git checkout –recursive but such a command doesn’t seem to exist.
Is there anyway to do this?


Solution 1:

You need two commands to achieve this:

git checkout *oldcommit*
git submodule update --recursive

Solution 2:

Note: if you have multiple submodules (and submodules inside submodules), Git 2.14 (Q3 2017) will help (more recent that the OP from 2013)

git checkout --recurse-submodules

Using --recurse-submodules will update the content of all initialized submodules according to the commit recorded in the superproject.
If local modifications in a submodule would be overwritten the checkout will fail unless -f is used.

git checkout --recurse-submodules” did not quite work with a
submodule that itself has submodules. It will with Git 2.14.

Note: with Git 2.19 (Q3 2018), git checkout --recurse-submodules another-branch is more robust.
Before, it did not report in which submodule it failed to update the working tree, which resulted in an unhelpful error message.

See commit ba95d4e (20 Jun 2018) by Stefan Beller (stefanbeller).
(Merged by Junio C Hamano — gitster in commit 392b3dd, 24 Jul 2018)

submodule.c: report the submodule that an error occurs in

When an error occurs in updating the working tree of a submodule in
submodule_move_head, tell the user which submodule the error occurred in.

The call to read-tree contains a super-prefix, such that the read-tree
will correctly report any path related issues, but some error messages
do not contain a path, for example:

~/gerrit$ git checkout --recurse-submodules origin/master
~/gerrit$ fatal: failed to unpack tree object 07672f31880ba80300b38492df9d0acfcd6ee00a

Give the hint which submodule has a problem.

Solution 3:

Depending on whether or not there are more submodules in the old checkout, you might have to do the following to initialize submodules that are not there any more in new commits:

git checkout *oldcommit*
git submodule init
git submodule update --recursive