解决Rails孤立迁移的最佳方法是什么?

我一直在项目中的分支之间切换,每个分支都有不同的迁移…这是场景:

$ rake db:migrate:status

Status Migration ID Migration Name -------------------------------------------------- ... up 20130307154128 Change columns in traffic capture up 20130311155109 Remove log settings up 20130311160901 Remove log alarm table up 20130320144219 ********** NO FILE ********** up 20130320161939 ********** NO FILE ********** up 20130320184628 ********** NO FILE ********** up 20130322004817 Add replicate to root settings up 20130403190042 ********** NO FILE ********** up 20130403195300 ********** NO FILE ********** up 20130403214000 ********** NO FILE ********** up 20130405164752 Fix ap hostnames up 20130410194222 ********** NO FILE ********** 

问题是rake db:rollback根本不起作用,因为缺少文件…

我该怎么办才能再次回滚并摆脱NO FILE消息?

顺便说一下, rake db:resetrake db:drop不是一个选项,我不能丢失来自其他表的数据……

我最终解决了这样的问题:

(1)转到具有迁移文件的分支并将其回滚。 如果您有许多分支,如果您尝试合并它们会导致许多冲突,这并非易事。 所以我用这个命令找出每个孤儿迁移所属的分支。

所以,我需要找到上次修改迁移的提交。

 git log --all --reverse --stat | grep  -C 10 

我接受提交哈希并确定它属于哪个分支,如下所示:

 git branch --contains  

然后我可以回到那个分支,做一个回滚并对所有丢失的文件重复这个过程。

(2)运行迁移:签出您最终要处理的分支并运行迁移,您应该好好去。

故障排除

我还运行了一些孤立迁移的情况,其中删除了分支。

为了解决这个问题,我使用与丢失文件相同的migration_id创建了虚拟迁移文件并将其回滚。 之后,我能够删除它们的虚拟迁移并具有干净的迁移状态:)

另一种方法是直接从数据库中删除丢失的文件:

 delete from schema_migrations where version=''; 

迁移存储在数据库中。 如果要删除已放弃的迁移,请从db中删除它们。

Postgres的例子:

  1. 打开psql:

     psql 
  2. 连接到您的数据库:

     \c your_database 
  3. 如果你很好奇,请显示schema_migrations:

     SELECT * FROM schema_migrations; 
  4. 如果您很好奇,请检查是否存在已放弃的迁移:

     SELECT version FROM schema_migrations WHERE version IN ('20130320144219', '20130320161939', '20130320184628', '20130403190042', '20130403195300', '20130403214000', '20130410194222'); 
  5. 删除它们:

     DELETE FROM schema_migrations WHERE version IN (); 

现在,如果您运行bundle exec rake db:migrate:status ,您将看到已成功删除孤立迁移。

编辑:如评论中所述,以下将删除您的数据库

一种更简单的方法对我有用(请注意,此命令将丢弃数据库,并且所有数据都将丢失):

rake db:migrate:reset

..然后:

rake db:migrate:status

孤儿应该消失。

假设您正在使用Git,那么抓住这些迁移并将它们带入当前分支应该相对简单。 如果你有一个特定的提交,你想要一个文件,你可以使用:

 git checkout   

(感谢这个答案 )

或者,您可以从特定分支HEAD查看:

 git checkout  --  

根据这篇博客文章

实际上,假设这些是在数据库上运行的迁移版本,您应该很好地回滚。

您可以将两个分支合并回主服务器,以便可以进行所有迁移。 如果您确实不希望那些迁移,但希望能够回滚,则可以编辑数据库中的schema_migrations表,以删除与您没有文件的迁移相对应的行。 但是,如果您切换到具有不同迁移的另一个分支,则会导致问题。

如果真的丢失了迁移文件(例如,运行迁移,忘记回滚迁移,然后在提交之前删除了迁移文件),我能够重现丢失的迁移,如下所示:

  1. 回到git历史记录中获取schema.rb文件的副本并保存在git repo之外( git log; git checkout xxxxxx; cp schema.rb ~/schema_old.rb, git checkout master)
  2. 对这两个文件运行diff,并将迁移命令复制到与缺少的迁移ID匹配的迁移文件中( diff schema.rb ~/schema_old.rb > migration_file.rb; vi migration_file.rb
  3. 检查迁移状态和回滚( rake db:migrate:status; rake db:rollback; rake db:migrate:status;