The Palaver and Perils of Removing a Git Submodule

In contrast to the simple single-line nicely-behaved “git submodule add” command, removing a submodule requires you to:

$ git submodule deinit -- path/to/submodule
$ rm -rf .git/modules/path/to/submodule
$ git rm -f path/to/submodule
$ git commit -a -m "Remove submodule"

Apart from the multiple steps with “rm -rf freely being tossed around willy-nilly, note the second command where you manually fiddle with the guts of the repository structure. That does not get propagated up to any remotes in a push or any repos that pull from you or a shared remote.


So, while you have just cleanly deleted a submodule from your repository, the job will only partially be done in downstream clones, and there is NOTHING you can do about it. It will not pose any issues (I think) … unless you later try to add a submodule of the same name/path but with a different URL (a common use case when a submodule changes owner/maintainer, for example). Then things will work fine on your repo, as you manually purged the old repo from the database, so you can freely add, commit, and push the new submodule. But when downstream repos pull from you, the whole house of cards is going to come tumbling down with some really clear but (in terms of how-to-fix-it) cryptic error messages.

It really is not nice.

It can only be fixed by manually repeating the following sticking-your-fingers-in-the-guts-of-the-beast approach in each of the cloned/downstream repos:

$ rm -rf .git/modules/path/to/submodule

followed by this to clean out the working trees of cloned/downstream repos:

$ rm -rf path/to/submodule



Or, if your intention was to move the submodule repo URL all along, there are other ways to do it), but these are no less problematical in terms of the manual work required in downstream repos to keep the accounts in order. The fact remains the entire process is messy, catastrophe-prone, and just plain … yucky.

But that’s what we have, so there it is.