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.

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

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.

This entry was posted in Code and tagged . Bookmark the permalink.

5 Responses to Changing git submodule URLs

  1. ch0wda says:

    Adam,

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

  2. Steve Eley says:

    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 says:

    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 says:

    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 says:

    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.

Leave a Reply

Your email address will not be published. Required fields are marked *

*

You may use these HTML tags and attributes: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <strike> <strong> <pre lang="" line="" escaped="">

Comments will be sent to the moderation queue.