# Fix Git Submodule Update Fails With Deleted Remote Reference

You clone a repository with submodules and run:

bash
git submodule update --init --recursive

Or update existing submodules:

bash
git submodule update --remote

And get an error:

bash
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' failed

The 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:

bash
git submodule status
git config --file .gitmodules --get-regexp url

This shows each submodule's path and remote URL:

bash
submodule libs/old-lib
    path = libs/old-lib
    url = https://github.com/org/deleted-repo.git
    branch = main

Step 2: Check If the Repository Was Renamed

Before removing the submodule, check if the repository was simply renamed:

bash
curl -sI https://github.com/org/deleted-repo | head -1

If it returns a 301 redirect, the repo was renamed. Update the URL:

bash
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:

bash
git submodule update --init libs/old-lib

Step 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:

bash
cd libs/mylib
git status
# HEAD detached at abc1234

This is normal. The superproject pins the submodule to a specific commit. If you want to work on the submodule, create a branch:

bash
git checkout -b feature-branch

Then commit in the submodule and update the superproject:

bash
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:

bash
git submodule update --init --recursive 2>&1 | grep fatal

This 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:

bash
git submodule sync --recursive
git submodule update --init --recursive

The sync command updates .git/config with the URLs from .gitmodules, then update fetches the actual content.

Preventing Submodule Breakage

  1. 1.Fork critical submodules: Maintain your own fork of submodules you depend on
  2. 2.Pin specific commits: Don't track branches; pin to specific commit hashes
  3. 3.Monitor upstream: Set up alerts for repositories your submodules depend on
bash
# 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"