I got fed up with the lack of best practice for working with Rails migrations across source control branches, so I decided to write a little Rails plugin. Here it is: the first release of Subverted Migrations!
This is a plugin that manages your migration versions across Subversion branches. It has two primary functions:
- It scans all of your Subversion branches and trunk to find a safe version number when creating migrations.
- It keeps track (à la svnmerge.py) of which migrations have been applied, and applies new migrations when they are merged back into the branch. (A detailed example exploring this feature is below.)
Warning
Careful, it's alpha! Please back up your schemas and data before trying this. At this time, it is only tested on OS X and PostgreSQL.
Getting It
script/plugin install \ svn://svn.madriska.com/plugins/subverted_migrations
Example (with Chunky Bacon)
Assume you have trunk and a ChunkyBacon branch (/branches/chunky_bacon). Both
have their latest migration at revision 010.
You create a migration in trunk:
[trunk]$ script/generate migration BoringBacon
exists db/migrate
create db/migrate/011_boring_bacon.rb
Next, you want to create a migration in branches/chunky_bacon. Without this
plugin, the new migration would have version number 011 and would create a
merge conflict. With the plugin, the version numbers are kept in sync:
[branches/chunky_bacon]$ script/generate migration ExtraCrispy
exists db/migrate
create db/migrate/012_extra_crispy.rb
The migration scripts should work as usual, but behind the scenes they keep
track of which migrations have been run, à la svnmerge.py. So let's say you
run the migration from the branch:
[branches/chunky_bacon]$ rake db:migrate Current version: 1-10 Target version: 1-12 == ExtraCrispy: migrating ================================================== (...) == ExtraCrispy: migrated (0.0000s) ========================================= Final version: 1-10,12
This indicates that the migrated version contains migrations 1-10 (from
before), as well as the ExtraCrispy revision (12). Once the Rake script detects
that a file matching "db/migrate/011_*" has been added, it will apply that
change as well. So if you merge the BoringBacon change from trunk into the
Chunky Bacon branch, just run "rake db:migrate" and it will pick up the new
change:
[branches/chunky_bacon]$ (svnmerge...) [branches/chunky_bacon]$ rake db:migrate Current version: 1-10,12 Target version: 1-12 == BoringBacon: migrating ================================================== (...) == BoringBacon: migrated (0.0000s) ========================================= Final version: 1-12
Note that version 11 has been incorporated, and now the version is 1-12.
You may also specify a version string on the command line. It can either be a
series of ranges or numbers separated by commas ("1-6,7,12-42") or a single
number, as before ("12", equivalent to "1-12"). To specify a single revision,
you must express it as a range (to migrate to revision 6 only, specify "6-6").
To back out the BoringBacon change, we would specify the version string that
removes version 11. The plugin includes a Rake task to show the current
version:
[branches/chunky_bacon]$ rake db:version 1-12
We remove 11 from the range and give the new range as an environment variable:
[branches/chunky_bacon]$ rake db:migrate VERSION="1-10,12" Current version: 1-12 Target version: 1-10,12 == BoringBacon: reverting ================================================== (...) == BoringBacon: reverted (0.0000s) ========================================= Final version: 1-10,12
And now the change is backed out.
Comments (3)
Hi
Just wonder if you know how this would work for those of us using eclipse as an IDE with subclipse as the subversion client.
Have you tried it using eclipse setup with aptana and RadRails.
Thanks for your contribution
David
Posted by David Southwell | August 18, 2007 9:33 AM
Posted on August 18, 2007 09:33
The plugin modifies Rails's own concept of what a migration number is, so I don't see any reason why it shouldn't work with RadRails. It does shell out to svn, so if you can't call svn from the command line you will have a problem. But you can change that in Madriska::SubvertedMigrations::CommandsBase#svn.
I used to use RadRails, but that was long before I wrote this plugin, so YMMV. Let me know if it works out.
Posted by Brad Ediger | August 18, 2007 10:51 AM
Posted on August 18, 2007 10:51
I have referenced your blog on:
http://www.aptana.com/forums/viewtopic.php?t=2519
Woulod be interested to hyave your reactions and wonder whether you might be willing to consider amending your code to work in the way suggested there.
david
Posted by David Southwell | August 18, 2007 11:11 AM
Posted on August 18, 2007 11:11