How to `git pull` all submodules without initializing the submodules

Viewed 235

Given a git repository with hundreds of submodules that I don't need or want to initialize because it would take a long time, how would I move the submodule pointer to the latest commit of each submodule?

If all the submodules were initialized I could use something like git submodule foreach git pull.

There may be some related gotchas like needing to specify which branch of each submodule to pull. In this case git should use the branch specified in the .gitmodules file for each submodule. I would like the command to go ahead and follow the specified branch even if a submodule's history has been rewritten. I would expect to get an error if the branch specified in the .gitmodules file does not exist.

Errors should either be reported at the end of the command output or sent to a log file so that they are not overlooked.

1 Answers

To get the sha1 of a branch on a remote without cloning the remote : use git ls-remote

git ls-remote <repourl> <branchname>

# example :
$ git ls-remote https://github.com/git/git master
f402ea68166bd77f09b176c96005ac7f8886e14b        refs/heads/master

To update the local sha1 of a submodule without cloning the submodule : use git update-index

git update-index --cacheinfo 160000,<sha1>,full/path/to/submodule
  • 160000 is a special filemode which indicates the object stored at this path is a commit (link to docs)
  • full/path/to/submodule should be the complete path, starting from the repo root, to the submodule
    e.g : if your submodule is stored in foo/bar/baz, even if your current working directory is foo/bar, you should specify foo/bar/baz as a path

More details on the 'update submodule' part

To my knowledge, there is no integrated command (e.g: a git submodule <something> command) to do this.

@torek gave a nice explanation of where the sha1 of a submodule is stored in this answer :

The hash ID is embedded [...] in the tree object for whatever directory contains the submodule reference.

The only way I know of to directly update this is git update-index command.

Error checking

git ls-remote <remote> <branch> :

  • this command will simply not output anything if the branch name you pass does not exist ; its exit code will indicate 'success' though

git update-index --cacheinfo ... :

  • this command will check that the path you are updating already exists
  • it will check that the sha1 is a 40 chars hexadecimal value
  • however, no check is performed on the validity of the sha1 at the time you update it (you don't have the repo at hand to check that the commit exists ...)
Related