I have been switching between branches in a project and each of them have different migrations... This is the scenario:
$ rake db:migrate:status
<
Assuming that you are using Git, it should be relatively simple to grab these migrations and bring them into your current branch. If you have a specific commit you want a file from, you can use:
git checkout <commit hash> <file_name>
(Thanks to this answer)
Alternatively, you can check out from a specific branch HEAD:
git checkout <branch name> -- <file_name>
According to this blog post
Assuming these are, in fact, the versions of the migrations run on the database, you should be good to rollback.
Edit: As said in the comments, the following WILL DROP YOUR DATABASE
A simpler approach that has worked for me (note that this command will drop the database and all your data will be lost):
rake db:migrate:reset
..and then:
rake db:migrate:status
The orphan(s) should disappear.
I ended up solving the problem like this:
(1) Go to the branches that has the migration files and roll them back. This is not trivial when you have many branches which are will result in many conflicts if you try to merge them. So I use this commands to find out the branches of each orphan migration belongs to.
So, I need to find commit of the last time the migration was modified.
git log --all --reverse --stat | grep <LASTEST_ORPHAN_MIGRATION_ID> -C 10
I take the commit hash and determine which branch it belongs like this:
git branch --contains <COMMIT_HASH>
Then I can go back to that branch, do a rollback and repeat this process for all the missing files.
(2) Run migrations: checkout the branch you finally want to work on and run the migrations and you should be good to go.
Troubleshooting
I also ran in some cases where orphaned migrations where on deleted branches.
To solve this I created dummy migration files with the same migration_id of the missing files and roll them back. After that, I was able to delete they dummy migrations and have a clean migration status :)
Another alternative is deleting the missing files from the database directly:
delete from schema_migrations where version='<MIGRATION_ID>';
A one liner for Rails console once you have the version numbers from failed rake db:migrate
or NO FILE entries from rake db:migrate:status
class SchemaMigration < ActiveRecord::Base; end; SchemaMigration.where(version: %i[the version numbers to delete]).delete_all
Which means, from terminal, you can
rails runner "class SchemaMigration < ActiveRecord::Base; end; SchemaMigration.where(version: %i[the version numbers to delete]).delete_all"
Though, at that point, it might be faster to use one of the direct database commands from previous answers.
create new files with names like
20130320144219_migration_1
put some blank code into
class Migration1 < ActiveRecord::Migration
def change; end
end
and run command rails db:migrate:down VERSION= 20130320144219
and at last - remove this files
If the migration files are truly missing (e.g. ran migration, forgot to roll back migration, then deleted migration file before commit), I was able to reproduce the missing migration as follows:
git log; git checkout xxxxxx; cp schema.rb ~/schema_old.rb, git checkout master)
.diff schema.rb ~/schema_old.rb > migration_file.rb; vi migration_file.rb
) rake db:migrate:status; rake db:rollback; rake db:migrate:status;
)