Migrations in Rails are quite nice. Basically what they give you is timestamped files containing steps needed to adjust the database and the data when going up and down in migration history.
See http://www.oracle.com/technology/pub/articles/kern-rails-migrations.html for a nice introduction.
I'd keep the timestamped files idea, that leaves the question where do we store what migrations have been applied already? A cache seems too fragile. Something like Migrations.yaml in Data/Persistent?
Then we don't have tables, but classes. No problem, we can map that easily. While we could try to diff class schemas and detect added and removed member variables. We don't need added ones, they will be just stored for any new instances and initialized to NULL (or rather not touched at all) during reconstitution. Removed ones don't do harm, aside from taking up space.
But isn't renaming of class members and changing the data inside what is most problematic? There is no way to automatically find out if "zip" used to be "postcode" and to change "year" from DateTime to integer using wild guesses.
So, Rails got quite some things right there with it's migration concept and making developers write down what needs to be changed.
Since a migration has up and down parts for going forth and back in time, it's easy to revert most things (see the ChangeAlbumYearToInteger migration example in the article linked above). Anyway, some stuff is irreversible, they say: really deleting stuff with drop_table and remove_column. Is it?
This is where TYPO3 was right for quite some time, renaming things to zzz_deleted_foobar instead of dropping right away. Now, if we would rename them and include the timestamp from the migration file, we could even restore such stuff.
I'll look into a nice syntax for this the next days...