Changing git submodule URLs

Pro-tip: if you’re using submodules with Git to manage dependencies (say Rails plugins), you can get yourself into trouble. Like half-a-day of wasted trouble.

The rub comes when you need to make a change to some plugin. Suppose you were using Brain Buster for your captcha and then decided you need to make a change. The @git submodule@ command doesn’t really seem to offer a way to change the URL for the submodule. Let me summarize what I’ve found in trying to do this.

h2{color: #f00}. The Wrong Way

* Fork/create your own version of the submodule in question
* Change the URL for the submodule in @.git/config@ and @.gitmodules@
* Cross your fingers and hope for the best

h2. The Right Way

* Fork/create your own version of the submodule in question
* Remove references to the existing submodule in @.git/config@, @.gitmodules@ and nuke the submodule directory
* Commit
* Add the new submodule URL
* Commit
* Make changes in your submodule
* Commit changes in the submodule (not the parent project)
* Commit the changes in the parent project (otherwise you’ll only get the old version of the submodule in future pulls)
* Enjoy the hair you didn’t have to rip from your scalp

Learn from my mistakes, people.

5 thoughts on “Changing git submodule URLs

  1. Yes, thank you! We’ve been trying to make submodules work for a repository of code shared between several applications, and the things submodules _don’t_ do that svn:externals did (like auto-updating) have been driving us nuts. We’re starting to wonder if it’s more trouble than it’s worth.

  2. Out of interest, what’s Wrong with The Wrong Way? As long as you fix up the repository URL in your local clone of the submodule (e.g. edit its .git/config, or just blow it away and git submodule update from scratch) it seems like it should chug along fine without having to completely nuke and re-add the whole submodule. What gives?

  3. Thanks for the tip. Just another thing that caused me trouble : when deploying with Capistrano you need to clear the shared/cached-copy directory or it will try to clone the old version of the plugin and fail with “Unable to checkout “.

    I now use this task when i change a submodule :

    namespace :deploy do
    task :clear_cached_copy do
    run <<-CMD
    rm -rf #{shared_path}/cached-copy

    and deploy with :
    cap deploy:clear_cached_copy
    cap deploy

    Maybe you could clear only the plugin subdirectory instead of the whole cached-copy and pass the plugin name to the task, I’ll have to try that.

  4. seems there is a way to do that properly:

    in the submodule directory do:
    git remote update
    git merge origin/master

    then you can add, commit and push the change to the submodule in your main project.

Comments are closed.