Categories
git git-submodules

How do I remove a submodule?

4145

How do I remove a Git submodule?
Why can’t I do
git submodule rm module_name?

4

  • 13

    That’s actually not true. That answer does not address removing the submodule entry from .git/config. The accepted answer shows the up-to-date way to fully remove a a submodule. It’s also explained more succinctly in this answer: stackoverflow.com/a/36593218/1562138

    – fvgs

    Apr 13, 2016 at 9:02


  • I found this article very helpful in removing submodules. It includes information on removing entries in the .gitsubmodules and .git/config files link

    – Ri_

    May 15, 2016 at 17:46


  • 18

    Please save yourself some time and directly go the answer that works (in 2017): stackoverflow.com/a/36593218/528313

    Jan 16, 2017 at 12:57

  • I’ve wrestled submodule problems for two days. The breakthrough came when I found this: forums.developer.apple.com/thread/13102. Basically, Xcode, and perhaps other apps, struggle to expand url’s containing ‘~’. Once I changed ssh://[email protected]/~/git/MyRepo.git to ssh://[email protected]/home/username/git/MyRepo.git (look up the actual path on your server), all the weirdness disappeared with ten minutes. See also stackoverflow.com/questions/32833100/…

    Feb 9, 2018 at 12:48

2579

Since git1.8.3 (April 22d, 2013):

There was no Porcelain way to say “I no longer am interested in this submodule”, once you express your interest in a submodule with “git submodule init“.
git submodule deinit” is the way to do so.

The deletion process also uses git rm (since git1.8.5 October 2013).

Summary

The 3-steps removal process would then be:

0. mv a/submodule a/submodule_tmp

1. git submodule deinit -f -- a/submodule    
2. rm -rf .git/modules/a/submodule
3. git rm -f a/submodule
# Note: a/submodule (no trailing slash)

# or, if you want to leave it in your working tree and have done step 0
3.   git rm --cached a/submodule
3bis mv a/submodule_tmp a/submodule

Explanation

rm -rf: This is mentioned in Daniel Schroeder‘s answer, and summarized by Eonil in the comments:

This leaves .git/modules/<path-to-submodule>/ unchanged.
So if you once delete a submodule with this method and re-add them again, it will not be possible because repository already been corrupted.


git rm: See commit 95c16418:

Currently using “git rm” on a submodule removes the submodule’s work tree from that of the superproject and the gitlink from the index.
But the submodule’s section in .gitmodules is left untouched, which is a leftover of the now removed submodule and might irritate users (as opposed to the setting in .git/config, this must stay as a reminder that the user showed interest in this submodule so it will be repopulated later when an older commit is checked out).

Let “git rm” help the user by not only removing the submodule from the work tree but by also removing the “submodule.<submodule name>” section from the .gitmodules file and stage both.


git submodule deinit: It stems from this patch:

With “git submodule init” the user is able to tell git they care about one or more submodules and wants to have it populated on the next call to “git submodule update“.
But currently there is no easy way they can tell git they do not care about a submodule anymore and wants to get rid of the local work tree (unless the user knows a lot about submodule internals and removes the “submodule.$name.url” setting from .git/config together with the work tree himself).

Help those users by providing a ‘deinit‘ command.
This removes the whole submodule.<name> section from .git/config either for the given
submodule(s)
(or for all those which have been initialized if ‘.‘ is given).
Fail if the current work tree contains modifications unless forced.
Complain when for a submodule given on the command line the url setting can’t be found in .git/config, but nonetheless don’t fail.

This takes care if the (de)initialization steps (.git/config and .git/modules/xxx)

Since git1.8.5, the git rm takes also care of the:

  • add‘ step which records the url of a submodule in the .gitmodules file: it is need to removed for you.
  • the submodule special entry (as illustrated by this question): the git rm removes it from the index:
    git rm --cached path_to_submodule (no trailing slash)
    That will remove that directory stored in the index with a special mode “160000”, marking it as a submodule root directory.

If you forget that last step, and try to add what was a submodule as a regular directory, you would get error message like:

git add mysubmodule/file.txt 
Path 'mysubmodule/file.txt' is in submodule 'mysubmodule'

Note: since Git 2.17 (Q2 2018), git submodule deinit is no longer a shell script.
It is a call to a C function.

See commit 2e61273, commit 1342476 (14 Jan 2018) by Prathamesh Chavan (pratham-pc).
(Merged by Junio C Hamano — gitster in commit ead8dbe, 13 Feb 2018)

git ${wt_prefix:+-C "$wt_prefix"} submodule--helper deinit \
  ${GIT_QUIET:+--quiet} \
  ${prefix:+--prefix "$prefix"} \
  ${force:+--force} \
  ${deinit_all:+--all} "[email protected]"

40

  • 21

    Can you given an example of usage for submodule deinit?

    – zakdances

    Apr 28, 2013 at 18:42

  • 5

    @yourfriendzak here is one example of someone successfully using it: stackoverflow.com/a/16161950/6309. But keep in mind that, contrary to what I originally believed, 1.8.3 is not yet released! On Unix, you can compile it from the sources.

    – VonC

    Apr 28, 2013 at 18:45

  • 2

    @HamishDowner the special entry should be gone (the directory is no longer a submodule), and the .gitmodules should be ok, but I would still double-check anything with the .git directory (ie the local config, within your local repo: that isn’t modified by a git pull)

    – VonC

    Jun 4, 2013 at 15:40

  • 2

    @Jayen yes, if you commit the removal of the .gitmodules entry and the removal of the special entry in the index, and push that repo, others can pull it and that submodule will be gone.

    – VonC

    Aug 2, 2013 at 6:04


  • 5

    In current git (v1.9+), plain old git rm submodule does exactly what you want as other people have already said.

    Jun 12, 2014 at 17:36

2579

Since git1.8.3 (April 22d, 2013):

There was no Porcelain way to say “I no longer am interested in this submodule”, once you express your interest in a submodule with “git submodule init“.
git submodule deinit” is the way to do so.

The deletion process also uses git rm (since git1.8.5 October 2013).

Summary

The 3-steps removal process would then be:

0. mv a/submodule a/submodule_tmp

1. git submodule deinit -f -- a/submodule    
2. rm -rf .git/modules/a/submodule
3. git rm -f a/submodule
# Note: a/submodule (no trailing slash)

# or, if you want to leave it in your working tree and have done step 0
3.   git rm --cached a/submodule
3bis mv a/submodule_tmp a/submodule

Explanation

rm -rf: This is mentioned in Daniel Schroeder‘s answer, and summarized by Eonil in the comments:

This leaves .git/modules/<path-to-submodule>/ unchanged.
So if you once delete a submodule with this method and re-add them again, it will not be possible because repository already been corrupted.


git rm: See commit 95c16418:

Currently using “git rm” on a submodule removes the submodule’s work tree from that of the superproject and the gitlink from the index.
But the submodule’s section in .gitmodules is left untouched, which is a leftover of the now removed submodule and might irritate users (as opposed to the setting in .git/config, this must stay as a reminder that the user showed interest in this submodule so it will be repopulated later when an older commit is checked out).

Let “git rm” help the user by not only removing the submodule from the work tree but by also removing the “submodule.<submodule name>” section from the .gitmodules file and stage both.


git submodule deinit: It stems from this patch:

With “git submodule init” the user is able to tell git they care about one or more submodules and wants to have it populated on the next call to “git submodule update“.
But currently there is no easy way they can tell git they do not care about a submodule anymore and wants to get rid of the local work tree (unless the user knows a lot about submodule internals and removes the “submodule.$name.url” setting from .git/config together with the work tree himself).

Help those users by providing a ‘deinit‘ command.
This removes the whole submodule.<name> section from .git/config either for the given
submodule(s)
(or for all those which have been initialized if ‘.‘ is given).
Fail if the current work tree contains modifications unless forced.
Complain when for a submodule given on the command line the url setting can’t be found in .git/config, but nonetheless don’t fail.

This takes care if the (de)initialization steps (.git/config and .git/modules/xxx)

Since git1.8.5, the git rm takes also care of the:

  • add‘ step which records the url of a submodule in the .gitmodules file: it is need to removed for you.
  • the submodule special entry (as illustrated by this question): the git rm removes it from the index:
    git rm --cached path_to_submodule (no trailing slash)
    That will remove that directory stored in the index with a special mode “160000”, marking it as a submodule root directory.

If you forget that last step, and try to add what was a submodule as a regular directory, you would get error message like:

git add mysubmodule/file.txt 
Path 'mysubmodule/file.txt' is in submodule 'mysubmodule'

Note: since Git 2.17 (Q2 2018), git submodule deinit is no longer a shell script.
It is a call to a C function.

See commit 2e61273, commit 1342476 (14 Jan 2018) by Prathamesh Chavan (pratham-pc).
(Merged by Junio C Hamano — gitster in commit ead8dbe, 13 Feb 2018)

git ${wt_prefix:+-C "$wt_prefix"} submodule--helper deinit \
  ${GIT_QUIET:+--quiet} \
  ${prefix:+--prefix "$prefix"} \
  ${force:+--force} \
  ${deinit_all:+--all} "[email protected]"

40

  • 21

    Can you given an example of usage for submodule deinit?

    – zakdances

    Apr 28, 2013 at 18:42

  • 5

    @yourfriendzak here is one example of someone successfully using it: stackoverflow.com/a/16161950/6309. But keep in mind that, contrary to what I originally believed, 1.8.3 is not yet released! On Unix, you can compile it from the sources.

    – VonC

    Apr 28, 2013 at 18:45

  • 2

    @HamishDowner the special entry should be gone (the directory is no longer a submodule), and the .gitmodules should be ok, but I would still double-check anything with the .git directory (ie the local config, within your local repo: that isn’t modified by a git pull)

    – VonC

    Jun 4, 2013 at 15:40

  • 2

    @Jayen yes, if you commit the removal of the .gitmodules entry and the removal of the special entry in the index, and push that repo, others can pull it and that submodule will be gone.

    – VonC

    Aug 2, 2013 at 6:04


  • 5

    In current git (v1.9+), plain old git rm submodule does exactly what you want as other people have already said.

    Jun 12, 2014 at 17:36

801

The majority of answers to this question are outdated, incomplete, or unnecessarily complex.

A submodule cloned using git 1.7.8 or newer will leave at most four traces of itself in your local repo. The process for removing those four traces is given by the three commands below:

# Remove the submodule entry from .git/config
git submodule deinit -f path/to/submodule

# Remove the submodule directory from the superproject's .git/modules directory
rm -rf .git/modules/path/to/submodule

# Remove the entry in .gitmodules and remove the submodule directory located at path/to/submodule
git rm -f path/to/submodule

11

  • 66

    Why this answer has so few upvotes? All those popular answers miss something, this is the only one that really removes all traces of a submodule, in the simplest possible way. And note: the order of commands matters.

    – mbdevpl

    Sep 7, 2016 at 6:08


  • 6

    @mbdevpl came 3 years after the accepted answer, and I guess no one’s managed to convince the OP to accept this one

    – Andy

    Feb 20, 2017 at 1:58

  • 24

    THIS is the not complicated answer in 2018?

    – Warren P

    Feb 2, 2018 at 22:43

  • 12

    the .gitmodules file still seems unaffected running these commands

    – Fractalf

    Sep 5, 2018 at 6:50

  • 6

    In 2019 this doesn’t work. The last line actually tries to remove from the .git/modules folder, which you’ve already removed in the above line. Adding -- to the first line like the accepted answer seems to make this work.

    – Fmstrat

    Jun 28, 2019 at 20:01