Overview
Git prints “No url found for submodule path '<path>' in .gitmodules” when a submodule’s path exists in the index (gitlink) but .gitmodules lacks a usable URL mapping. This shows up during clone, checkout, or git submodule update --init --recursive, especially in CI.
This guide (DevOps, Git) shows how to diagnose and fix mapping issues fast.
Quickstart (most cases)
- Inspect mappings:
- View what Git expects:
git ls-files --stage | grep '^160000' || true git submodule status || true - Check .gitmodules:
test -f .gitmodules && cat .gitmodules || echo ".gitmodules missing" git config -f .gitmodules -l || true
- View what Git expects:
- Sync config, then init/update:
git submodule sync --recursive git submodule update --init --recursive - If it still fails, add the missing mapping and commit it:
# Replace NAME, PATH, URL with real values git config -f .gitmodules submodule.NAME.path PATH git config -f .gitmodules submodule.NAME.url URL git add .gitmodules git commit -m "Fix .gitmodules: add URL for submodule PATH" git submodule sync --recursive git submodule update --init --recursive - One-off CI workaround (if you cannot commit right now):
# Temporary local fix for this checkout only git config submodule.NAME.url URL git submodule update --init --recursive
Minimal working example (reproduce and fix)
This script creates a repo with a submodule, breaks its URL mapping, shows the error, then fixes it.
set -euxo pipefail
rm -rf /tmp/demo-parent /tmp/demo-lib /tmp/demo-clone || true
# Create a library repo
git init /tmp/demo-lib
cd /tmp/demo-lib
printf 'v1\n' > lib.txt
git add lib.txt
git commit -m "lib: v1"
# Create parent and add submodule
cd /tmp
git init demo-parent
cd demo-parent
mkdir -p lib
git submodule add /tmp/demo-lib lib/demo-lib
git commit -m "add submodule lib/demo-lib"
# Break mapping: remove URL from .gitmodules
git config -f .gitmodules --unset submodule.lib/demo-lib.url || true
cat .gitmodules || true
git add .gitmodules
git commit -m "break: missing URL for lib/demo-lib"
# Clone elsewhere and try to init submodules (will fail)
cd /tmp
git clone /tmp/demo-parent demo-clone
cd demo-clone
set +e
err=$(git submodule update --init --recursive 2>&1) || true
echo "$err" | sed -n '1,5p'
set -e
# Fix by restoring URL mapping and update
LIB_URL=/tmp/demo-lib
NAME=lib/demo-lib
PATH=lib/demo-lib
git config -f .gitmodules submodule."$NAME".path "$PATH"
git config -f .gitmodules submodule."$NAME".url "$LIB_URL"
git add .gitmodules
git commit -m "fix: add URL for $PATH"
git submodule sync --recursive
git submodule update --init --recursive
Diagnose the root cause
- .gitmodules missing or missing URL:
.gitmodulesmust contain entries:submodule.<name>.path = <path>submodule.<name>.url = <url>
- Check quickly:
git config -f .gitmodules --name-only --get-regexp '^submodule\..*\.(path|url)$'
- Path mismatch:
- The path in
.gitmodulesmust match the path staged as a gitlink:git ls-files --stage | awk '$1==160000{print $4}'
- The path in
- Stale local config:
- Local
.git/configmay have outdatedsubmodule.<name>.url. Sync:git submodule sync --recursive git config -l | grep '^submodule\.' || true
- Local
- Removed/renamed submodule:
- Gitlink exists but mapping removed or path changed.
- Lost
.gitmodules:- Recover from history or remote:
git restore --source=HEAD -- .gitmodules || true # or from a remote branch git restore --source=origin/MAIN -- .gitmodules || true
- Recover from history or remote:
Fixes by scenario
Add a missing mapping (permanent)
# Identify the submodule name used in .gitmodules (choose a stable name) NAME=components-api PATH=lib/components-api [email protected]:org/components-api.git git config -f .gitmodules submodule."$NAME".path "$PATH" git config -f .gitmodules submodule."$NAME".url "$URL" git add .gitmodules git commit -m "submodule($PATH): add URL mapping" git submodule sync --recursive git submodule update --init --recursiveRename/move a submodule path
old=lib/old-api new=lib/new-api name=api git mv "$old" "$new" git config -f .gitmodules submodule."$name".path "$new" git add .gitmodules git commit -m "submodule($name): move to $new" git submodule sync --recursive git submodule update --init --recursiveRemove a submodule cleanly
path=lib/unused git submodule deinit -f "$path" git rm -f "$path" rm -rf ".git/modules/$path" git config -f .gitmodules --remove-section submodule."$path" || true git add .gitmodules || true git commit -m "remove submodule $path"Temporary CI fix (no repo write access)
# If you know the correct URL but cannot change the repo git config submodule.NAME.url https://example.com/repo.git git submodule update --init --recursive --depth 1 --jobs 8Synchronize stale local config
git submodule sync --recursive git submodule update --init --recursive
Common symptoms and quick remedies
| Symptom | Likely cause | Quick fix |
|---|---|---|
| No url found for submodule path 'X' | Missing submodule.*.url | Add URL to .gitmodules, commit, sync |
| No submodule mapping found for path 'X' | No entry in .gitmodules | Add path+url entry or remove gitlink |
| Submodule path changed but URL ignored | Path in .gitmodules differs | Update submodule.*.path, move dir, sync |
Pitfalls
- Editing
.gitmoduleslocally but forgetting to commit and push it. - Manually moving submodule directories without updating
submodule.*.path. - Deleting the submodule folder with your OS instead of using
git submodule deinitandgit rm. - Assuming
.git/configchanges persist for others; only.gitmodulesis shared. - Relative URLs that no longer resolve after a remote layout change.
Performance notes
- Speed up initialization in CI:
git submodule update --init --recursive --depth 1 --jobs 8 - Cache dependencies between builds (runner-specific): use a mirror or
--referenceto reuse objects.git clone --recursive --reference /cache/mirror.git <url> repo git submodule update --init --recursive --depth 1 --jobs 8 - Avoid unnecessary recursion when you know submodules don’t have submodules:
git submodule update --init --depth 1 --jobs 8
FAQ
- What is .gitmodules vs .git/config?
.gitmodulesis versioned and shared;.git/configis local. Always fix mappings in.gitmodulesand commit.
- How do I find the submodule name?
- Names are the keys under
submodule.<name>.*. List them with:git config -f .gitmodules --get-regexp '^submodule\..*\.path$'
- Names are the keys under
- Can I fix without committing?
- Yes, set
git config submodule.NAME.url ...as a temporary workaround. Commit a proper fix later.
- Yes, set
- Does shallow clone cause this error?
- Not directly. This error is about missing URL mapping, not history depth.
- How do I recover a deleted .gitmodules?
- Restore from history or from your remote branch, commit it, then
git submodule syncandupdate.
- Restore from history or from your remote branch, commit it, then