Before Bundler came to save us all from dependency hell, it was pretty common to check in specific versions of plugins and gems into a Rails app’s vendor directory. Unfortunately, due to our flawed nature as mortal developers, the temptation to make that one little change directly in the vendor’d code sometimes proved to be too great to master.
The result: forked and frozen code whose change history is deeply integrated into the entire project’s history, making upgrading nearly impossible.
But with Bundler and its integration with git there’s little reason for this. Your app can depend on your own private version of the gem. If you’re a good open source citizen, having a separate gem will make it easily to contribute your changes back.
Checkout this Gist for how to extract a plugin (in this case active_shipping) and preserve its changes. [One of these days I just need to move my blog over to GitHub and be done with it… but I digress…]
If your codebase is like mine was, the first commit included both the initial plugin import and a bunch of changes. If that’s the case, you’ll probably have some conflicts to resolve. But if you’re hear, hopefully you know how to do that.
Also, you might take the chance to rewrite your history to remove references to project specific things in comments so that when you push changes to the public gem the authors don’t have to pick through the accumulated history of years of your project’s secret-garden-development. Again, that’s something left to other tutorials.
Anyway, the most amazing part to me was git-filter-branch, which I learned about in this Stack Overflow question. A word of warning though: this tool can have some sharp edges. I think Patrick Thomson said it best: “filter-branch really should be renamed to nuclear-chainsaw considering how dangerous and powerful it is.”