我在分支中添加了一个迁移"add_dogs"迁移db/migrate/20221220155010_create_dogs.rb
,运行db:migrate
。
后来,我改变了分支(没有合并),最终放弃了"new_dog "分支。
后来,我查看了"add_cats"用db/migrate/20221101010101_create_cats.rb
支路,用db:migrate
支路。到目前为止,一切都很好。
然后我调整了"add_cats"迁移(在提交任何东西之前),并运行db:rollback
,以便我可以再次运行它。我得到这个错误:
ActiveRecord::UnknownMigrationVersionError:
No migration with version number 20221220155010.
我仍然可以在新的迁移上运行db:migrate
,但不能运行db:rollback
或db:migrate:redo
。
这是有意义的,因为数据库有应用20221220155010
的记录,但是该迁移文件不再存在,所以没有办法回滚它。
我怎样才能通过这个?
根据您的需要和访问权限,有三种方法可以处理丢失的迁移文件:
- 对于一个快速的临时修复,您可以回滚您当前正在编辑的迁移,以便您可以再次运行它。如果另一个迁移仍然在另一个分支的管道中,并且两者最终将被合并,那么这可能是有用的。
rake db:migrate:down VERSION=20230101010101
// This is the version of the migration you WANT to rollback, not the missing one.
- 如果丢失的迁移永远不会回来,您需要永久修复。最简单的方法是从数据库中删除该记录。您可以从您最喜欢的SQL客户端、rails控制台等完成此操作(我认为您甚至可以编写迁移来完成此操作,但这似乎强大粗略。)
DELETE FROM schema_migrations WHERE version = '20221220155010'
-- This is the version of the migration that is MISSING, not the one you are working on.
- 如果由于某种原因不能直接访问数据库,可以给Rails一个回滚的安慰剂。确保文件名中的时间戳与丢失的迁移版本号匹配。
创建名为db/migrations/20221220155010_just_kidding.rb
:
class JustKidding < ActiveRecord::Migration
def change
# nothing to see here.
end
end
然后,rails db:rollback
将回滚该无操作迁移,并从schema_migrations表中删除20221220155010
。现在,您可以永远删除安慰剂迁移,并且您将在运行迁移和回滚方面处于良好状态。
然而…不要忘记,旧迁移的效果仍然在您的模式中。也许你遇到了一个新的、未使用过的"dogs"表,或者表上多了一列。也许这在您的开发设备上是无害的,但您肯定不希望在生产环境中出现这种乱七八糟的东西。这个答案中的所有建议都假设您处于一个一次性环境中,并且旧迁移的影响不是问题。在这种情况下,拆除整个数据库并重新构建可能是一个更有吸引力的选择。
这里真正的收获之一是……首先不要让这种情况发生!理想情况下,您应该在从分支更改之前回滚任何新的、未提交的迁移。但是…事情发生…
注。如果有办法从命令行做到这一点,我很乐意学习。我想象rails db:migrate:delete VERSION=20230101010101
这样的东西可能会以一种hackish的方式方便。