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/configand.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,.gitmodulesand 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.
Tags: git
-
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.
-
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?
-
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
endand deploy with :
cap deploy:clear_cached_copy
cap deployMaybe 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.
-
seems there is a way to do that properly:
in the submodule directory do:
git remote update
git merge origin/masterthen you can add, commit and push the change to the submodule in your main project.




5 comments
Comments feed for this article