2

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.

Jonathan
  • 39
  • 1
  • 6

1 Answers1

4

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 ...)
LeGEC
  • 46,477
  • 5
  • 57
  • 104
  • This just prints the hash of latest commit on a branch. The question is asking for a way to update submodule pointers for hundreds of submodules automatically. – DV82XL Jun 29 '20 at 18:03
  • 1
    @DV82XL : you were right, I thought there was a clearly identified file to update, it turned out the command to update a single submodule was hidden deeper than I thought – LeGEC Jun 30 '20 at 22:03
  • 1
    there is no integrated command, but submodule are repos themselves. If I can do a [shallow-clone](https://stackoverflow.com/questions/23708231/git-shallow-clone-clone-depth-misses-remote-branches) on a regular repo, why not on a submodule? – Daemon Painter Aug 14 '20 at 10:56
  • The OP asked for a solution with no submodule initialization at all, so I tried to answer that. Using "shallow clone" as you suggest can be a nice way to avoid a full clone too. – LeGEC Aug 14 '20 at 12:21