# Fix Git Submodule Update Fails With Deleted Remote Reference
You clone a repository with submodules and run:
git submodule update --init --recursiveOr update existing submodules:
git submodule update --remoteAnd get an error:
fatal: repository 'https://github.com/org/deleted-repo.git/' not found
fatal: clone of 'https://github.com/org/deleted-repo.git' into submodule path '/path/to/submodule' failedThe submodule points to a repository that has been deleted, made private, or renamed.
Step 1: Identify the Broken Submodule
List all submodules and their URLs:
git submodule status
git config --file .gitmodules --get-regexp urlThis shows each submodule's path and remote URL:
submodule libs/old-lib
path = libs/old-lib
url = https://github.com/org/deleted-repo.git
branch = mainStep 2: Check If the Repository Was Renamed
Before removing the submodule, check if the repository was simply renamed:
curl -sI https://github.com/org/deleted-repo | head -1If it returns a 301 redirect, the repo was renamed. Update the URL:
git submodule set-url libs/old-lib https://github.com/org/new-repo-name.git
git add .gitmodules
git commit -m "Update submodule URL after repository rename"Then update:
git submodule update --init libs/old-libStep 3: Remove the Dead Submodule
If the repository is truly gone, remove the submodule:
```bash # Step 1: Deinitialize the submodule git submodule deinit -f libs/old-lib
# Step 2: Remove from .gitmodules git rm libs/old-lib
# Step 3: Remove the .git/modules entry rm -rf .git/modules/libs/old-lib
# Step 4: Commit the changes git commit -m "Remove dead submodule libs/old-lib" ```
The git submodule deinit removes the submodule from .git/config. The git rm removes it from .gitmodules and the working tree. The .git/modules directory cleanup removes cached data.
Step 4: Replace With a Fork or Alternative
If the submodule was critical, find a replacement:
```bash # Add the new submodule git submodule add https://github.com/fork-org/replacement-repo.git libs/new-lib
# Initialize and update git submodule update --init libs/new-lib
# Commit git commit -m "Replace dead submodule with fork" ```
Step 5: Submodule Not Updating to Latest Commit
If the submodule exists but git submodule update --remote does not fetch the latest:
```bash # Fetch the submodule directly cd libs/mylib git fetch origin git checkout main cd ../..
# Or from the root git submodule update --remote --merge libs/mylib ```
The --remote flag fetches the latest commit from the submodule's tracked branch. The --merge flag merges instead of detaching HEAD.
Step 6: Detached HEAD in Submodule
After git submodule update, the submodule is in a detached HEAD state:
cd libs/mylib
git status
# HEAD detached at abc1234This is normal. The superproject pins the submodule to a specific commit. If you want to work on the submodule, create a branch:
git checkout -b feature-branchThen commit in the submodule and update the superproject:
git add .
git commit -m "Update submodule feature"
cd ../..
git add libs/mylib
git commit -m "Update submodule to latest"Step 7: Recursive Submodule Issues
With --recursive, nested submodules can also fail:
git submodule update --init --recursive 2>&1 | grep fatalThis filters to show only the failing submodules. Fix each one individually.
Step 8: Submodule Sync After URL Changes
If the remote URL changes for multiple submodules:
git submodule sync --recursive
git submodule update --init --recursiveThe sync command updates .git/config with the URLs from .gitmodules, then update fetches the actual content.
Preventing Submodule Breakage
- 1.Fork critical submodules: Maintain your own fork of submodules you depend on
- 2.Pin specific commits: Don't track branches; pin to specific commit hashes
- 3.Monitor upstream: Set up alerts for repositories your submodules depend on
# Pin to a specific commit instead of a branch
git submodule add -b main https://github.com/org/repo.git libs/repo
cd libs/repo
git checkout abc1234 # Pin to specific commit
cd ../..
git add libs/repo
git commit -m "Pin submodule to abc1234"