Search code examples
gitruby-on-rails-pluginsgit-submodules

switching a subdirectory managed by git to a submodule


We used to have a local hack of delayed_job in a Rails app, in vendor/plugins/delayed_job. It was installed as a one-time event and checked into git in the main app repo.

Now we decided to fork delayed_job on github and replace the subdirectory by a git submodule, as described e.g. here:

http://doblock.com/articles/using-git-submodules-to-manage-plugins-in-rails

Before doing that, I simply removed vendor/plugins/delayed_job, without checking it in. Now, despite adding the submodule, git status in the main repo still shows new files in vendor/plugins/delayed_job.

How should we handle the situation where a subdirectory which was a part of the repo is deleted and made to hold a git submodule? Should we first delete it with git rm, or obliterate it even more thoroughly, before cloning a submodule into its place?


Solution

  • Assuming that you do not care about the current contents of vendor/plugins/delayed_job in your working tree (i.e. the content that will be checked out as a submodule is already a suitable replacement for the content in your working tree), the normal procedure for converting a directory into a submodule looks like this:

    git rm -r vendor/plugins/delayed_job
    git submodule add github.com:account/delayed_job.git vendor/plugins/delayed_job
    

    Of course, the GitHub repository URL may vary; for example, you may want to use an HTTP URL instead of the above SSH URL.

    But, it seems like you did something a bit different. As best I can tell, you did something like this:

    rm -rf vendor/plugins/delayed_job
    git clone github.com:account/delayed_job.git vendor/plugins/delayed_job
    

    There are two flaws with this procedure:

    1. The plain rm leaves the old files in your Git index.
    2. Directly cloning gives you a “subrepository”, but not an official submodule.

    Assuming that you do not have any intentionally staged changes in vendor/plugins/delayed_job (you probably do not, since you are replacing it with a submodule), you can clean up the situation with these commands:

    git rm --cached -r vendor/plugins/delayed_job
    git submodule add github.com:account/delayed_job.git vendor/plugins/delayed_job
    

    Cleaning out all the vendor/plugins/delayed_job entries from the index should fix your “still shows new files” problem. Using git submodule add will create the .gitmodules file which turns the “subrepository” into a true submodule.