Introduction

Git submodules reference external repositories at specific commits. When the submodule's remote repository is deleted, moved to a new URL, or made private, git submodule update fails:

bash
git submodule update --init --recursive
# Cloning into 'lib/old-dep'...
# fatal: repository 'https://github.com/org/old-dep.git/' not found
# fatal: clone of 'https://github.com/org/old-dep.git' into submodule path 'lib/old-dep' failed

This breaks the build for all developers and CI/CD pipelines.

Symptoms

  • git submodule update fails with "repository not found"
  • Clone of the parent repository fails during submodule initialization
  • CI/CD pipeline fails at the submodule checkout step
  • Error about authentication or 404 for the submodule URL
  • Some developers can update (cached submodule) while others cannot

Common Causes

  • Submodule repository was deleted from GitHub/GitLab
  • Repository was renamed, changing the URL
  • Repository was made private and credentials are not available
  • Organization transferred the repository to a new namespace
  • The submodule URL in .gitmodules was never updated after a migration

Step-by-Step Fix

  1. 1.Update the submodule URL in .gitmodules:
  2. 2.```bash
  3. 3.git submodule set-url lib/old-dep https://github.com/org/new-dep.git
  4. 4.git add .gitmodules
  5. 5.git commit -m "Update submodule URL for old-dep"
  6. 6.`
  7. 7.Update the local submodule configuration:
  8. 8.```bash
  9. 9.git submodule sync
  10. 10.git submodule update --init --recursive
  11. 11.`
  12. 12.If the repository was moved, update all references:
  13. 13.```bash
  14. 14.# Edit .gitmodules directly
  15. 15.[submodule "lib/old-dep"]
  16. 16.path = lib/old-dep
  17. 17.url = https://github.com/org/new-location.git

# Then sync git submodule sync rm -rf lib/old-dep git submodule update --init lib/old-dep ```

  1. 1.Remove the submodule entirely if it is no longer needed:
  2. 2.```bash
  3. 3.git submodule deinit -f lib/old-dep
  4. 4.rm -rf .git/modules/lib/old-dep
  5. 5.git rm -f lib/old-dep
  6. 6.rm -rf lib/old-dep
  7. 7.git commit -m "Remove orphaned submodule old-dep"
  8. 8.`
  9. 9.Replace with a package manager dependency instead of a submodule:
  10. 10.```bash
  11. 11.# For Node.js projects
  12. 12.npm install @org/new-dep@latest
  13. 13.# For Python projects
  14. 14.pip install new-dep
  15. 15.`
  16. 16.Then remove the submodule and update the project to use the package.

Prevention

  • Avoid submodules when possible - prefer package managers (npm, pip, cargo) for dependencies
  • Monitor submodule repository status and get notified before they are deleted
  • Use git submodule set-url to update URLs promptly when repositories move
  • Keep a .github/dependabot.yml or equivalent to track submodule updates
  • Document all submodules and their purpose in the project README
  • Mirror critical submodule repositories to a backup location you control
  • Use subtree merges (git subtree) instead of submodules for internal dependencies
  • Test submodule cloning in CI/CD pipelines as part of the build verification