4

I've read how to remove a git submodule myself:

# Delete the relevant section from the .gitmodules file.
git config -f .gitmodules --remove-section submodule.$submodulepath
# Delete the relevant section from .git/config
git config -f .git/config --remove-section submodule.$submodulepath
git rm --cached path_to_submodule    # no trailing slash
git commit
rm -rf path_to_submodule

I can do that. But when someone else does a git pull how do we ensure that the submodule is then removed from their system? The .gitmodules change comes with the pull, but not much else as far as I can tell. So the person who pulled would then still have to run

git config -f .git/config --remove-section submodule.$submodulepath
rm -rf path_to_submodule

Is that right? On a small development team I guess you could just tell everyone to run those commands, but it's less than ideal.

Is there some magic command that automates this? In particular I'd like some standard way of automating this in deployment scripts. Off the top of my head I'm not sure how the scripts would even know that there was one less submodule than there previously was. (Not particularly attractive) options that occur to me are:

  • doing diffs on .gitmodules before and after pull
  • delete all submodules and then run git submodule update --init every single deploy.
  • The submodule does end up being an untracked file after the pull, so an option that would work would be to delete all untracked directories that contain a .git subdirectory after a pull, but you're liable to delete stuff you wanted to keep that way.

Any better options appreciated.

Community
  • 1
  • 1
Hamish Downer
  • 16,603
  • 16
  • 90
  • 84
  • Shouldn't the `git rm` command you executed remove the submodel on a pull? – Daniel Hilgarth Feb 14 '13 at 15:01
  • @DanielHilgarth: it didn't get removed when we did it recently, but maybe I didn't do the exact steps above. Maybe I should test that. – Hamish Downer Feb 14 '13 at 15:09
  • @DanielHilgarth: Just checked and `git rm` does not actually remove the submodule files, hence the `rm -rf path_to_submodule` at the end of the first set of instructions. The cloned copy also needs the manual delete step. Is this different for you? If so, what version of git are you using? – Hamish Downer Feb 14 '13 at 15:17
  • I didn't test that. I just thought that git rm works the same for submodules as it does for normal files. – Daniel Hilgarth Feb 14 '13 at 15:25
  • @DanielHilgarth: you would assume it would, I agree. But git has a way of not matching your assumptions with respect to the behaviour of command line utilities and arguments ... – Hamish Downer Feb 14 '13 at 15:28
  • is `git clean -df` an option for you? it removes *everything* that isn't tracked – CharlesB Feb 19 '13 at 10:56
  • @CharlesB: There are often some untracked files I wouldn't want to remove, particularly in development environments. I can't expect everyone to be really disciplined about adding stuff to .gitignore - and .gitignore could get pretty messy. If nothing else is available I guess it could be used for deployment to servers, while developers have to manually delete the submodule, but I'd rather find a clean solution. – Hamish Downer Feb 19 '13 at 11:43

1 Answers1

1

For deploying code to servers having a git clean run after pull (via a post-checkout hook for example) is a safe option.

As for updating developers' repos, where running git clean is dangerous, I know no other way than pruning by hand.

However the following (untested) script will do it automatically, name it something like git prune-submodules. It relates on the fact that after git pull, removed submodules are still listed in .git/config, so you can find out which one is to be archived.

I'm quite novice in shell scripting, so please double-check.

#!/bin/sh
#get the list of submodules specified in .git/config
#http://stackoverflow.com/questions/1260748/how-do-i-remove-a-git-submodule#comment9411108_7646931
submodules_cfg=`git config -f .git/config -l | cut -d'=' -f1 | grep "submodule.$MODPATH" | sed 's/^submodule\.//' | sed 's/\.url$//'`

#get the list of current submodules
submodules=`git submodule | cut -b 2- | cut -d' ' -f 2`

#archive submodule if listed in .git/config but doesn't exist anymore
for submodule_cfg in $submodules_cfg; do
    submodule_cfg_exists=0
    for submodule in $submodules; do
         if [ "$submodule" == "$submodule_cfg" ]; then
              submodule_cfg_exists=1
         fi
    done

    if ["$submodule_cfg_exists" == 0]; then
        mkdir -p archived-submodules
        mv $submodule_cfg archived-submodules/
        git config -f .git/config --remove-section submodule.$submodule_cfg
    fi
done
CharlesB
  • 86,532
  • 28
  • 194
  • 218