Git Submodules

I had some trouble dealing with submodules. This is what I experienced, learned, and did to solve the issue.

Using a custom SSH URL

Let's see if our repository has submodules:

$ git submodule
 9d83ae91cffb5840a5ff722e9f1dabc2d74c96ae vagrant/cookbooks (9d83ae9)

Yes, it does. Take a look at the submodule details which are stored in .gitmodules; it should look like this:

[submodule "vagrant/cookbooks"]
    path = vagrant/cookbooks
    url = git@github.com:AcmeCorporation/FlagshipProduct-cookbooks.git

Unfortunately, that's not the URL we want to use but instead we have a dedicated alias in ~/.ssh/config:

Host github
    HostName github.com
    User git
    IdentityFile ~/.ssh/id_rsa_github

But first, initialize the submodule (this has to be done from the repository's root path):

$ git submodule init
Submodule 'vagrant/cookbooks' (git@github.com:AcmeCorporation/FlagshipProduct-cookbooks.git) registered for path 'vagrant/cookbooks'

Make sure that there is an URL shown between the parentheses; if there isn't, something is already wrong.

That step should have added a section to .git/config:

[…]
[submodule "vagrant/cookbooks"]
    url = git@github.com:AcmeCorporation/FlagshipProduct-cookbooks.git

If we would have tried to update the submodule with the original SSH URL, this might fail:

$ git submodule update
Permission denied (publickey).
fatal: The remote end hung up unexpectedly
Unable to fetch in submodule path 'vagrant/cookbooks'

Just adjust the SSH URL in .git/config as necessary (in our case, use above SSH host alias):

[…]
[submodule "vagrant/cookbooks"]
    url = github:AcmeCorporation/FlagshipProduct-cookbooks.git

Now we can finally update the submodule:

$ git submodule update
Cloning into 'vagrant/cookbooks'...
remote: Counting objects: 302, done.
remote: Compressing objects: 100% (216/216), done.
remote: Total 302 (delta 86), reused 273 (delta 59)
Receiving objects: 100% (302/302), 149.71 KiB | 198 KiB/s, done.
Resolving deltas: 100% (86/86), done.
Submodule path 'vagrant/cookbooks': checked out '9d83ae91cffb5840a5ff722e9f1dabc2d74c96ae'

Yay! :)

Troubleshooting

This happened to me after I initialized the submodule:

$ git submodule update
fatal: Needed a single revision
Unable to find current revision in submodule path 'vagrant/cookbooks'

An FAQ by Gostai states:

This is the sign that the initial checkout […] went completely wrong (I don’t know what makes this happen). Chances are that the directory exists, but is empty. Git does not seem to be able to overcome this situation, […]

So just delete the submodule's directory:

$ rm -rf vagrant/cookbooks

As pointed out in a comment to an answer on Stack Overflow, this might not be sufficient, so delete Git's internal related directory, too:

$ rm -rf .git/modules/vagrant/cookbooks

Now start again by initializing or updating the submodule.