7

Solution: remove --cached from git rm -r --cached submodule/name. Scripted for reference.


I'm trying to remove a git submodule based on this SO answer, but the submodule is not being removed.

I add the submodule, commit the changes, then delete it using git rm -r --cached $path/to/submodule (minus the trailing / ), commit the changes, but the submodule is still there.

I can use rm -rf submodules/lift_sbt_24 to delete the folder and contents, but why isn't git rm -r --cached doing that?

(deleting the relevant section from .gitmodules works fine, is no problem, hence not mentioned here)

This is git 1.7.5.4 on Ubuntu 11.10, fwiw. Complete example:

$> git submodule add git@github.com:lift-stack/lift_24_sbt.git submodules/lift_24_sbt
Adding submodule from repo git@github.com:lift-stack/lift_24_sbt.git as submodules/lift_24_sbt
Cloning into submodules/lift_24_sbt...
remote: Counting objects: 619, done.
remote: Compressing objects: 100% (375/375), done.
remote: Total 619 (delta 172), reused 593 (delta 147)
Receiving objects: 100% (619/619), 1.74 MiB | 112 KiB/s, done.
Resolving deltas: 100% (172/172), done.
$> git status
# On branch master
# Your branch is ahead of 'origin/master' by 1 commits.
#
# Changes to be committed:
#   (use "git reset HEAD <file>..." to unstage)
#
#   modified:   .gitmodules
#   new file:   submodules/lift_24_sbt
#
$> git add -a
$> git commit 'added submodules/lift_24_sbt'
[master 9894113] update
 2 files changed, 4 insertions(+), 0 deletions(-)
 create mode 160000 submodules/lift_24_sbt
$> git rm -r --cached submodules/lift_24_sbt
rm 'submodules/lift_24_sbt'
$> git status
# On branch master
# Your branch is ahead of 'origin/master' by 1 commits.
#
# Changes to be committed:
#   (use "git reset HEAD <file>..." to unstage)
#
#   deleted:    submodules/lift_24_sbt
#
# Untracked files:
#   (use "git add <file>..." to include in what will be committed)
#
#   submodules/lift_24_sbt/
$> git add -a
$> git commit -m 'deleted submodules/lift_24_sbt'
# On branch master
# Your branch is ahead of 'origin/master' by 1 commits.
#
nothing to commit (working directory clean)
$> ls -al submodules/lift_24_sbt/
total 1060
drwxr-xr-x 5 kurtosis kurtosis    4096 2012-04-18 17:26 ./
drwxrwxr-x 6 kurtosis kurtosis    4096 2012-04-18 17:26 ../
drwxrwxr-x 8 kurtosis kurtosis    4096 2012-04-18 17:32 .git/
drwxrwxr-x 2 kurtosis kurtosis    4096 2012-04-18 17:26 project/
drwxrwxr-x 3 kurtosis kurtosis    4096 2012-04-18 17:26 src/
-rw-rw-r-- 1 kurtosis kurtosis     931 2012-04-18 17:26 build.sbt
-rw-rw-r-- 1 kurtosis kurtosis     463 2012-04-18 17:26 .gitignore
-rw-rw-r-- 1 kurtosis kurtosis      91 2012-04-18 17:26 README.md
-rwxrwxr-x 1 kurtosis kurtosis     110 2012-04-18 17:26 sbt*
-rw-rw-r-- 1 kurtosis kurtosis     131 2012-04-18 17:26 sbt.bat
-rw-rw-r-- 1 kurtosis kurtosis 1041753 2012-04-18 17:26 sbt-launch.jar
$> git --version
git version 1.7.5.4
Community
  • 1
  • 1
bgibson
  • 17,379
  • 8
  • 29
  • 45

2 Answers2

12

What you're seeing is correct; git rm --cached -r does not, in fact, remove the files from the working tree, only from the index. If you want git to remove the files from both the index and the working tree, you shouldn't use --cached. See the git-rm man page for further information.


Following is an explanation of what you did. I am assuming that you typed out the steps you took, rather than copying from a terminal; as far as I'm aware, git add -a is not a known git-add flag; I am also fairly sure you also meant git commit -m <message>.

The cut-down steps you've taken:


# First, add the submodule. 
$> git submodule add git@github.com:lift-stack/lift_24_sbt.git submodules/lift_24_sbt
# Check that the submodule exists. (It does). 
$> git status
# Add everything to the staging area from the working tree. 
$> git add -a
# Commit all changes. 
$> git commit 'added submodules/lift_24_sbt'

At this point, you've successfully added the module, and everything is working as expected.
What you try to do next is to remove the module:

$> git rm -r --cached submodules/lift_24_sbt

Note: here, we do not remove the files from the working index, only from the index, because of the --cached:

--cached
       Use this option to unstage and remove paths only from the index. Working tree
       files, whether modified or not, will be left alone.

Then, check that we've removed the submodule:

$> git status
... <snip> 
# Changes to be committed:
#   (use "git reset HEAD <file>..." to unstage)
#
#   deleted:    submodules/lift_24_sbt

As you can see, the submodule has been deleted, and everything is good. Note, however, that the files still exist in the working tree - you can still view them with ls. :)

simont
  • 68,704
  • 18
  • 117
  • 136
  • Thanks, and yes I meant `git add -A` and `git commit -m`. Removed --cached from `git rm -r $1` and [scripted it](https://github.com/byrongibson/scripts/blob/master/git-rm-submodule.sh). Maybe not wise to do this in a script, but it's at least useful as a step-by-step reference. – bgibson May 07 '12 at 20:17
1

You can try and simpliyfy your script, by using a new command (git1.8.3, April 22d, 2013), detailed in a new answer to "How do I remove a Git submodule?":

git submodule deinit

It should remove the submodule working tree as well as unregister it from .git/config.

Community
  • 1
  • 1
VonC
  • 1,262,500
  • 529
  • 4,410
  • 5,250