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

时间:2022-09-15 20:51:28

I have been switching between branches in a project and each of them have different migrations... This is the scenario:

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

$ rake db:migrate:status

$ 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 **********

The problem is rake db:rollback don't work at all because of the missing files...

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

What should I do to be able to rollback again and get rid of the NO FILE messages?

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

Btw, rake db:reset or rake db:drop are not an option, I cannot lose data from other tables...

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

6 个解决方案

#1


44  

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.

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

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.

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

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 :)

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

Another alternative is deleting the missing files from the database directly:

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

delete from schema_migrations where version='<MIGRATION_ID>';

#2


16  

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

rake db:migrate:reset

..and then:

..接着:

rake db:migrate:status

rake db:migrate:status

The orphan(s) should disappear.

孤儿应该消失。

#3


12  

Migrations are stored in your database. If you want to remove the abandoned migrations, remove them from the db.

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

Example for Postgres:

Postgres的例子:

  1. Open psql:

    打开psql:

    psql
    
  2. Connect to your db:

    连接到您的数据库:

    \c your_database
    
  3. If you're curious, display schema_migrations:

    如果你很好奇,请显示schema_migrations:

    SELECT * FROM schema_migrations;
    
  4. If you're curious, check if the abandoned migrations are present:

    如果您很好奇,请检查是否存在已放弃的迁移:

    SELECT version FROM schema_migrations WHERE version IN 
    ('20130320144219', '20130320161939', '20130320184628', '20130403190042',
     '20130403195300', '20130403214000', '20130410194222');
    
  5. Delete them:

    删除它们:

    DELETE FROM schema_migrations WHERE version IN (<version list as above>);
    

Now if you run bundle exec rake db:migrate:status, you'll see the orphaned migrations have been successfully removed.

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

#4


0  

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,那么抓住这些迁移并将它们带入当前分支应该相对简单。如果你有一个特定的提交,你想要一个文件,你可以使用:

git checkout <commit hash> <file_name>

(Thanks to this answer)

(感谢这个答案)

Alternatively, you can check out from a specific branch HEAD:

或者,您可以从特定分支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.

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

#5


0  

You could merge the two branches back into the master so that you have all migrations available. If you really don't want those migrations there, but want to be able to roll back, you could edit the schema_migrations table in your database to remove the rows corresponding to the migrations for which you don't have files. However, this will cause problems if you then switch to another branch with different migrations.

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

#6


0  

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:

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

  1. go back in git history to get a copy of the schema.rb file and save outside of git repo (git log; git checkout xxxxxx; cp schema.rb ~/schema_old.rb, git checkout master).
  2. 回到git历史记录中获取schema.rb文件的副本并保存在git repo之外(git log; git checkout xxxxxx; cp schema.rb~ / schema_old.rb,git checkout master)。
  3. run a diff on the two files, and copy the migration commands into a migration file that matches the missing migration ID (diff schema.rb ~/schema_old.rb > migration_file.rb; vi migration_file.rb)
  4. 对这两个文件运行diff,并将迁移命令复制到与缺少的迁移ID匹配的迁移文件中(diff schema.rb~ / schema_old.rb> migration_file.rb; vi migration_file.rb)
  5. Check your migration status and rollback (rake db:migrate:status; rake db:rollback; rake db:migrate:status;)
  6. 检查迁移状态和回滚(rake db:migrate:status; rake db:rollback; rake db:migrate:status;)

#1


44  

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.

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

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.

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

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 :)

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

Another alternative is deleting the missing files from the database directly:

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

delete from schema_migrations where version='<MIGRATION_ID>';

#2


16  

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

rake db:migrate:reset

..and then:

..接着:

rake db:migrate:status

rake db:migrate:status

The orphan(s) should disappear.

孤儿应该消失。

#3


12  

Migrations are stored in your database. If you want to remove the abandoned migrations, remove them from the db.

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

Example for Postgres:

Postgres的例子:

  1. Open psql:

    打开psql:

    psql
    
  2. Connect to your db:

    连接到您的数据库:

    \c your_database
    
  3. If you're curious, display schema_migrations:

    如果你很好奇,请显示schema_migrations:

    SELECT * FROM schema_migrations;
    
  4. If you're curious, check if the abandoned migrations are present:

    如果您很好奇,请检查是否存在已放弃的迁移:

    SELECT version FROM schema_migrations WHERE version IN 
    ('20130320144219', '20130320161939', '20130320184628', '20130403190042',
     '20130403195300', '20130403214000', '20130410194222');
    
  5. Delete them:

    删除它们:

    DELETE FROM schema_migrations WHERE version IN (<version list as above>);
    

Now if you run bundle exec rake db:migrate:status, you'll see the orphaned migrations have been successfully removed.

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

#4


0  

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,那么抓住这些迁移并将它们带入当前分支应该相对简单。如果你有一个特定的提交,你想要一个文件,你可以使用:

git checkout <commit hash> <file_name>

(Thanks to this answer)

(感谢这个答案)

Alternatively, you can check out from a specific branch HEAD:

或者,您可以从特定分支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.

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

#5


0  

You could merge the two branches back into the master so that you have all migrations available. If you really don't want those migrations there, but want to be able to roll back, you could edit the schema_migrations table in your database to remove the rows corresponding to the migrations for which you don't have files. However, this will cause problems if you then switch to another branch with different migrations.

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

#6


0  

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:

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

  1. go back in git history to get a copy of the schema.rb file and save outside of git repo (git log; git checkout xxxxxx; cp schema.rb ~/schema_old.rb, git checkout master).
  2. 回到git历史记录中获取schema.rb文件的副本并保存在git repo之外(git log; git checkout xxxxxx; cp schema.rb~ / schema_old.rb,git checkout master)。
  3. run a diff on the two files, and copy the migration commands into a migration file that matches the missing migration ID (diff schema.rb ~/schema_old.rb > migration_file.rb; vi migration_file.rb)
  4. 对这两个文件运行diff,并将迁移命令复制到与缺少的迁移ID匹配的迁移文件中(diff schema.rb~ / schema_old.rb> migration_file.rb; vi migration_file.rb)
  5. Check your migration status and rollback (rake db:migrate:status; rake db:rollback; rake db:migrate:status;)
  6. 检查迁移状态和回滚(rake db:migrate:status; rake db:rollback; rake db:migrate:status;)