50

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

$ rake db:迁移:状态

 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:reset或者rake db:drop不是一个选项,我不能从其他表中丢失数据......

4

10 回答 10

62

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

(1)到有迁移文件的分支回滚。当您有许多分支时,这并非微不足道,如果您尝试合并它们会导致许多冲突。所以我使用这个命令来找出每个孤儿迁移所属的分支。

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

git log --all --reverse --stat | grep <LASTEST_ORPHAN_MIGRATION_ID> -C 10

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

git branch --contains <COMMIT_HASH>

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

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

故障排除

在某些情况下,我还在删除的分支上运行了孤立迁移。

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

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

delete from schema_migrations where version='<MIGRATION_ID>';
于 2013-04-22T19:39:59.830 回答
49

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

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 (<version list as above>);
    

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

于 2016-10-25T14:41:18.010 回答
25

这是来自@medik 的 psql 答案的 rake 版本,它不会擦除您的数据库或做任何疯狂的事情:

1) 找到您的孤立迁移版本:

rails db:migrate:status

2) 记下缺少迁移的版本并进入数据库控制台:

rails dbconsole

3) 现在手动从迁移表中删除版本:

delete from schema_migrations where version='[version_number]';
于 2019-07-19T16:17:49.217 回答
19

编辑:以下将删除您的数据库

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

rake db:migrate:reset

..接着:

rake db:migrate:status

孤儿应该消失。

于 2014-03-13T18:32:14.603 回答
4

创建具有名称的新文件,例如 20130320144219_migration_1 将一些空白代码放入

class Migration1 < ActiveRecord::Migration 
  def change; end 
end 

并运行命令rails db:migrate:down VERSION= 20130320144219 ,最后 - 删除这些文件

于 2020-04-20T18:16:50.427 回答
2

这是我为此目的编写的一个 rake 任务。db:migrate:status它调用与引擎盖下使用的方法相同的方法,ActiveRecord::Base.connection.migration_context.migrations_status

# lib/tasks/cleanup_migration_entries.rake

desc 'Removes schema_migration entries for removed migration files'
task 'db:migrate:cleanup': :environment do
  migration_context = ActiveRecord::Base.connection.migration_context
  versions_to_delete =
    migration_context.migrations_status
                     .filter_map { |_status, version, name| version if name.include?('NO FILE') }

  migration_context.schema_migration.delete_by(version: versions_to_delete)

  puts "Cleaned up #{versions_to_delete.size} orphaned migrations."
end
于 2020-09-01T21:57:49.197 回答
0

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

git checkout <commit hash> <file_name>

(感谢这个答案

或者,您可以从特定分支 HEAD 签出:

git checkout <branch name> -- <file_name>

根据这篇博文

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

于 2013-04-16T23:42:58.820 回答
0

您可以将两个分支合并回主分支,以便您拥有所有可用的迁移。如果您真的不希望这些迁移在那里,但希望能够回滚,您可以编辑数据库中的 schema_migrations 表以删除与您没有文件的迁移相对应的行。但是,如果您随后切换到具有不同迁移的另一个分支,这将导致问题。

于 2013-04-20T07:13:45.000 回答
0

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

  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;)
于 2017-02-01T16:39:22.110 回答
0

rake db:migrate一旦您获得来自失败或没有文件条目的版本号,Rails 控制台的一个衬垫rake db:migrate:status

 class SchemaMigration < ActiveRecord::Base; end; SchemaMigration.where(version: %i[the version numbers to delete]).delete_all

这意味着,从终端,您可以

rails runner "class SchemaMigration < ActiveRecord::Base; end; SchemaMigration.where(version: %i[the version numbers to delete]).delete_all"

但是,在那时,使用先前答案中的直接数据库命令之一可能会更快。

于 2020-06-04T14:36:27.410 回答