git clean is not removing a submodule added to a branch when switching branches

Solution 1:

This isn't a bug, it's documented behaviour. From man git-clean:

If an untracked directory is managed by a different git repository, it is not removed by default.

The submod directory is a different git repository; if you want to remove it, Use -f option twice if you really want to remove such a directory.

git clean -f -f -d submod does remove submod. See my steps below (almost identical; different git version and hard-coded submodule path because otherwise git spits the dummy).


Steps


$ git --version
git version 1.7.5.4 # Note, different git-version. 

Make the two repositories


git init submod
cd submod
echo "This is a submodule" > README.txt
git add .
git commit -m "Initial commit"
cd ..
git init prog
cd prog
echo "This is a program" > README.txt
git add .
git commit -a -m "Initial commit"

Add submod as a git submodule in topic1 branch.


git checkout -b topic1
git submodule add /Users/simont/sandbox/SOTESTING/Subdir-testing/submod
git commit -m "Added submodule"

Now for the interesting section.


$ git checkout master
warning: unable to rmdir submod: Directory not empty
Switched to branch 'master'

git status
# On branch master
# Untracked files:
#   (use "git add ..." to include in what will be committed)
#
#       submod/
#nothing added to commit but untracked files present (use "git add" to track)

Attempt to git-clean, then actually git-clean.


git clean -fd
#Removing submod/

git status
# On branch master
# Untracked files:
#   (use "git add ..." to include in what will be committed)
#
#       submod/
#nothing added to commit but untracked files present (use "git add" to track)

$ # As we can see, we haven't actually removed anything yet. 
$ ls
README.txt  submod

$ git clean -f -f -d submod
Removing submod/

$ ls
README.txt

$ git status
# On branch master
nothing to commit (working directory clean)

Solution 2:

To remove the "leftover" submodules after checking out a different branch, you can run the following. This command will recursively clean the main repository and all submodules. Warning: this will remove all untracked files as well.

git clean -xffd && git submodule foreach --recursive git clean -xffd

To see which files will be deleted without actually deleting yet, add the -n flag.

git clean -nxffd && git submodule foreach --recursive git clean -nxffd

Key to the command is the double-f passed to Git clean. Without that, Git will not remove folders that are a submodule (i.e. folders containing a .git subfolder).