One of the most common issues users can experience when setting up a Deploy project is a submodule related error. These can be tricky to diagnose, so, in this post we'll be outlining a number of common errors and checks that can be made in the event of one.

Submodule mapping

When adding code to your app from another source, for example a library or plugin, you can use Git submodules. Submodules are, in essence, an external Git repository kept as a subdirectory in your own repo.

Git repositories reference submodules using a .gitmodules file which tells Git where to get the submodule from and where the files need to reside in your repository. This allows you to easily update your repository with a new version of the submodule when it has been updated at source.

The most common error experienced occurs when the files have been cloned from another repository, but not added as a submodule meaning no reference has been created. This often results in the following error displayed in Deploy:

No submodule mapping found for path/to/directory

For reference, the normal procedure for adding a new submodule is as follows:

$ git submodule add https://source-repository-url/repository.git path/to/directory

Once this process has completed, a mapping entry will be added to .gitmodules like so:

[submodule "path/to/directory"] 
  path = path/to/directory 
  url = https://source-repository-url/repository.git

If that file and entry is not present, Deploy will not be able to clone the submodule's files and the mapping error will be displayed. In this instance, you can update .gitmodules to contain the correct mapping using the above format as reference.

If you've made any changes, just run the following command to update Git locally:

$ git submodule sync

Then the command below to ensure that everything is present and correct. If it is, you'll see a commit reference checked out from the source repository.

$ git submodule status
012345689abcdef path/to/directory (heads/master)

Submodule authentication

In a lot of cases such as Wordpress, plugins and themes added as submodules in your repository won't require authentication as they're hosted on public repositories on Github.

However, submodules may be hosted within a private repository. Deploy's process doesn't allow interaction when authenticating with a remote repository, which would normally allow you to enter a username and password in the same way as a local terminal or Git client. Therefore, you'll need to add the repository using SSH authentication.

If needed, you can modify your .gitmodules file to use an SSH URL instead of HTTP, with the following format:

git@repohost.com:account/repository.git

The SSH URL can be easily retrieved from your repository host via the main browser, normally located just above your list of files. If this change is needed, you can run git submodule sync to update it.

For Deploy to be able to authenticate using SSH, your project's public key will need to be added to the source repository's deployment keys. We have a number of articles that describe the process in further detail for the main supported repository hosts in our documentation:

Otherwise, on a self-hosted repository server it will be a case of adding the key to your authorized_keys file.

Github does have a restriction that only allows a deployment key to be used on a single repository, but they offer a solution whereby you can create a machine user and assign the deployment key to that user, which will then be given access to multiple Github repositories, allowing you to add the key to multiple submodules and/or your main repository, depending on where that's hosted.

More information on this can be found in Github's documentation.

Changes to submodules

Another error that can be difficult to diagnose is the following:

fatal: reference is not a tree: 123456789abcdef
Unable to checkout '123456789abcdef' in submodule path 'my-submodule'

This occurs when the local, checked out commit reference doesn't exist in the remote, either because it no longer exists in the remote, or more likely that changes have been committed locally and not pushed there. If it's the later and the changes do need to be pushed, simply navigate to the submodule directory and push them to the remote:

$ cd my-submodule
$ git push

Otherwise, if the changes are not intended, you can cd to the submodule directory and checkout a reference that does exist in the remote:

$ cd my-submodule
$ git checkout abcdef123456789

Then git submodule status can be run from your root directory to ensure that you now have the correct reference checked out. Once resolved, push the changes and you should be good to go.

Further reading

We recommend you take a look at the excellent guide on submodules found on git-scm, otherwise if you have any questions, please don't hesitate to get in touch.

Tell us how you feel about this post?