How do I remove a submodule? – Dev

The best answers to the question “How do I remove a submodule?” in the category Dev.

QUESTION:

How do I remove a Git submodule?

By the way, is there a reason I can’t simply do
git submodule rm whatever ?

ANSWER:

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]"

ANSWER:

Via the page Git Submodule Tutorial:

To remove a submodule you need to:

  1. Delete the relevant section from the .gitmodules file.
  2. Stage the .gitmodules changes:
    git add .gitmodules
  3. Delete the relevant section from .git/config.
  4. Remove the submodule files from the working tree and index:
    git rm --cached path_to_submodule (no trailing slash).
  5. Remove the submodule’s .git directory:
    rm -rf .git/modules/path_to_submodule
  6. Commit the changes:
    git commit -m "Removed submodule <name>"
  7. Delete the now untracked submodule files:
    rm -rf path_to_submodule

See also: alternative steps below.

ANSWER:

Just a note. Since git 1.8.5.2, two commands will do:

git rm -r the_submodule
rm -rf .git/modules/the_submodule

As @Mark Cheverton’s answer correctly pointed out, if the second line isn’t used, even if you removed the submodule for now, the remnant .git/modules/the_submodule folder will prevent the same submodule from being added back or replaced in the future. Also, as @VonC mentioned, git rm will do most of the job on a submodule.

–Update (07/05/2017)–

Just to clarify, the_submodule is the relative path of the submodule inside the project. For example, it’s subdir/my_submodule if the submodule is inside a subdirectory subdir.

As pointed out correctly in the comments and other answers, the two commands (although functionally sufficient to remove a submodule), do leave a trace in the [submodule "the_submodule"] section of .git/config (as of July 2017), which can be removed using a third command:

git config -f .git/config --remove-section submodule.the_submodule 2> /dev/null

ANSWER:

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