How to checkout old git commit including all submodules recursively?

GitGit Submodules

Git Problem Overview


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?

Git Solutions


Solution 1 - Git

You need two commands to achieve this:

git checkout *oldcommit*
git submodule update --recursive

Update: This answer is outdated as of 2018 – see VonC's answer below for more current information.

Solution 2 - Git

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 - Git

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

Attributions

All content for this solution is sourced from the original question on Stackoverflow.

The content on this page is licensed under the Attribution-ShareAlike 4.0 International (CC BY-SA 4.0) license.

Content TypeOriginal AuthorOriginal Content on Stackoverflow
QuestionBen BaronView Question on Stackoverflow
Solution 1 - GitChronialView Answer on Stackoverflow
Solution 2 - GitVonCView Answer on Stackoverflow
Solution 3 - GitThomasView Answer on Stackoverflow