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. ch0wda June 5, 2008 / 3:30 PM

    Adam,

    Thanks, I have learned from your mistakes. This yak still has all it’s hair.

  2. Steve Eley June 9, 2008 / 1:59 PM

    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.

  3. Tom July 1, 2008 / 8:34 AM

    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?

  4. Matthieu Sadouni January 25, 2009 / 4:25 AM

    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
    CMD
    end
    end

    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.

  5. david June 12, 2009 / 8:05 AM

    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.