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:
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' failedThis breaks the build for all developers and CI/CD pipelines.
Symptoms
git submodule updatefails 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
.gitmoduleswas never updated after a migration
Step-by-Step Fix
- 1.Update the submodule URL in
.gitmodules: - 2.```bash
- 3.git submodule set-url lib/old-dep https://github.com/org/new-dep.git
- 4.git add .gitmodules
- 5.git commit -m "Update submodule URL for old-dep"
- 6.
` - 7.Update the local submodule configuration:
- 8.```bash
- 9.git submodule sync
- 10.git submodule update --init --recursive
- 11.
` - 12.If the repository was moved, update all references:
- 13.```bash
- 14.# Edit .gitmodules directly
- 15.[submodule "lib/old-dep"]
- 16.path = lib/old-dep
- 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.Remove the submodule entirely if it is no longer needed:
- 2.```bash
- 3.git submodule deinit -f lib/old-dep
- 4.rm -rf .git/modules/lib/old-dep
- 5.git rm -f lib/old-dep
- 6.rm -rf lib/old-dep
- 7.git commit -m "Remove orphaned submodule old-dep"
- 8.
` - 9.Replace with a package manager dependency instead of a submodule:
- 10.```bash
- 11.# For Node.js projects
- 12.npm install @org/new-dep@latest
- 13.# For Python projects
- 14.pip install new-dep
- 15.
` - 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-urlto update URLs promptly when repositories move - Keep a
.github/dependabot.ymlor 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