Many version controls systems today have some form of “external” or “submodule” feature that’s basically just a way to embed one repository (or a piece of one) in another. After working with a few of these systems in a variety of scenarios, I’ve come to the conclusion that they are more trouble than they’re worth. But I didn’t know of any good alternatives… until now.
I’ve discovered that Bundler is very useful as a “repository manager.” It’s not just useful for Ruby projects; you don’t even need to use gems! You can keep all projects/libraries as simple repositories (with no externals) wherever you want, and have Bundler keep track of things for you. (A similar but slightly different method is also very useful for managing tools. See: Stealing Ruby Gems)
Step One
For each repository that is depended on by other repositories, put a .gemspec file and a tiny ruby script in the root. (The Ruby file can relocated.) They should look something like this:
The Ruby script is simply a little helper file that we can use to get the path to our library, whether it’s in some local directory, an installed gem, or an installed gem fetched from a git repo.
Step Two
In a project that depends on these libraries, add a Gemfile similar to the following:
Bundler gives you a lot of control over where your “gem” can come from. You can have it pull from a local directory, a git repository, or a regular gem. See Bundler’s page on gemfiles for more information.
Step Three
In your project, add a Ruby script like this to get the path of your library (no matter where it is):
If you’re using Rake or Ceedling or another Ruby-based build system, you can just require my_awesome_lib directly and use My_Awesome_Lib.location where ever a path to your library is needed.
Step Four
On the command line, go to where you have the Gemfile and type: bundle install.
And that’s it! You should now be able to use my_awesome_lib_path.rb (or similar) to get the path to your library (for use in your include paths in your build system or whatever).
If you want to change where you’re pulling your library from, you just have to change the Gemfile.


One Comment
You can make this even simpler in two steps.
1) Use Bundler’s capability to generate a stub gemspec by omitting the per-repository gemspecs and instead specifying an arbitrary version (e.g. 0.0.0) in the Gemfile.
2) Use Gem.loaded_specs["mygem"].gem_dir instead of having a file only dedicated to yielding its own path.