Easy Git External Dependency Management with Giternal
Anyone building up a project with many dependencies - and in the Ruby community, with so much functionality wrapped up in gems and plugins, it's hard to imagine not having external dependencies! - must face the issue of managing the situation in source code control. How do you maintain everything you need in your own repository, while still being able to update your dependencies from their own repository? How do you set things up so you can even contribute to the projects you depend on?
If you're using git, the right answer is often the subtree merge strategy - but remembering the necessary commands can be a nuisance, especially if you rarely use them. There are several projects out there designed to make this easier for you: Tim Dysinger published some rake tasks to handle subtrees, and Braid is a more full-featured tool to manage both git- and svn-based vendor branches. 37signals have also released cached_externals which provides a somewhat different solution to the problem using symbolic links and separated checkouts.
After trying all of those approaches, though, I've settled on Pat Maddox's giternal tool for my own work. With giternal, you add a YAML file with details on your project's dependencies, similar to this:
delayed_job: repo: git://github.com/tobi/delayed_job.git path: vendor/plugins paperclip: repo: git://github.com/thoughtbot/paperclip.git path: vendor/plugins
After that, there are just three commands to remember:
giternal update to update all of your dependencies,
giternal freeze to create a self-contained deploy tag with all externals at a known version, and
giternal unfreeze to go back to live subtrees. If you've been shying away from dealing with externals in your git repositories, give it a shot.