Remove a Git submodule from a repository

Unregister and remove a submodule without discarding its local work, commit the superproject change, and distinguish removal from optional metadata cleanup.

Best practices
Illustration of Git branches and version history

Check and preserve work inside the submodule before removing it. For a clean submodule, unregister the local checkout with git submodule deinit, then remove the tracked submodule entry with git rm and commit the superproject change.

Inspect the submodule first

git -C vendor/lib status
git -C vendor/lib log --oneline --branches --not --remotes
git -C vendor/lib rev-parse --git-dir

The log comparison depends on locally stored remote-tracking refs and does not cover every detached or tag-only commit. Inspect the actual checked-out commit too, and save or publish needed work deliberately. Record the Git directory if you plan to consider storage cleanup later.

Remove it from the current version

From the superproject root:

git submodule deinit -- vendor/lib
git rm -- vendor/lib
git diff --cached
git commit -m "Remove vendor/lib submodule"

Deinitialization unregisters the submodule locally and clears its working tree. git rm stages removal of the gitlink and normally updates and stages the relevant .gitmodules entry. Review the staged diff rather than assuming every configuration is now absent.

The non-force commands can refuse when local work would be lost. Inspect that work before deciding whether a force option is appropriate; deinit -f can remove a modified submodule working tree.

Verify the result

Check .gitmodules, git status, and the relevant local submodule configuration. Other submodules should remain intact. If .gitmodules becomes empty, you may remove it explicitly with git rm -- .gitmodules and include that deletion in the commit.

Keeping the submodule's repository under the superproject's Git metadata is normal. It can help when checking out an older superproject commit that still references the submodule. Removing that storage is optional and can destroy local-only history. Its location is based on the submodule's configured name and repository layout, not necessarily a literal .git/modules/PATH string.

FAQ

Why not just delete the directory?

That removes working-tree files without necessarily removing the index gitlink, .gitmodules entry, or local registration. Later submodule commands can recreate it or report an inconsistent state.

How can I add it back?

Use git submodule add URL vendor/lib after checking the current state, or restore the appropriate historical superproject change. Existing retained metadata may affect how Git handles the new add; inspect any message instead of deleting it automatically.

Can I turn it into a normal directory?

Save the files outside the submodule first, remove the submodule, then copy the intended source files back without their Git metadata and add them normally. This preserves the files, not the submodule's commit history. Use a planned subtree/history import when retaining that history is required.

What does “not removing recursively” mean?

Inspect what Git thinks the path is with git ls-files --stage -- vendor/lib. A tracked directory and a submodule gitlink are different cases; that error is not proof that a submodule merely has uncommitted changes.

See git-submodule and git-rm.

Get a tailored plan

Contact us

Join the community

Scan with WeChat
to join the community

Try Guance

Start online and pay only for what you use.

Get started

Choose a Guance plan

Code hosting