git 解决 Rails 孤立迁移的最佳方法是什么?
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/16041790/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
What is the best way to resolve Rails orphaned migrations?
提问by Adrian
I have been switching between branches in a project and each of them have different migrations... This is the scenario:
我一直在一个项目中的分支之间切换,每个分支都有不同的迁移......这是场景:
$ 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
不是一个选项,我不能丢失其他表中的数据......
回答by Adrian
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 :)
为了解决这个问题,我创建了与丢失文件具有相同迁移 ID 的虚拟迁移文件并将它们回滚。之后,我能够删除他们的虚拟迁移并拥有干净的迁移状态:)
Another alternative is deleting the missing files from the database directly:
另一种选择是直接从数据库中删除丢失的文件:
delete from schema_migrations where version='<MIGRATION_ID>';
回答by medik
Migrations are stored in your database. If you want to remove the abandoned migrations, remove them from the db.
迁移存储在您的数据库中。如果要删除废弃的迁移,请将它们从数据库中删除。
Example for Postgres:
Postgres 示例:
Open psql:
psql
Connect to your db:
\c your_database
If you're curious, display schema_migrations:
SELECT * FROM schema_migrations;
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');
Delete them:
DELETE FROM schema_migrations WHERE version IN (<version list as above>);
打开 psql:
psql
连接到您的数据库:
\c your_database
如果您好奇,请显示 schema_migrations:
SELECT * FROM schema_migrations;
如果您好奇,请检查是否存在已放弃的迁移:
SELECT version FROM schema_migrations WHERE version IN ('20130320144219', '20130320161939', '20130320184628', '20130403190042', '20130403195300', '20130403214000', '20130410194222');
删除它们:
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
,您将看到孤立的迁移已成功删除。
回答by spandata
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.
孤儿应该消失。
回答by stackPusher
Here is a rake version of the psql answer from @medik, which won't erase your db or do anything crazy:
这是来自@medik 的 psql 答案的 rake 版本,它不会删除您的数据库或做任何疯狂的事情:
1) Find your orphaned migration versions:
1) 找到您的孤立迁移版本:
rails db:migrate:status
2) Note the versions of the missing migrations and head into the db console:
2)注意缺少的迁移版本并进入数据库控制台:
rails dbconsole
3) Now remove the versions from the migration table manually:
3)现在手动从迁移表中删除版本:
delete from schema_migrations where version='[version_number]';
回答by Evseev Vadim
create new files with names like
20130320144219_migration_1
put some blank code into
使用名称创建新文件,例如
20130320144219_migration_1
将一些空白代码放入
class Migration1 < ActiveRecord::Migration
def change; end
end
and run command rails db:migrate:down VERSION= 20130320144219
and at last - remove this files
并运行命令rails db:migrate:down VERSION= 20130320144219
,最后 - 删除此文件
回答by Taylored Web Sites
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:
如果迁移文件确实丢失(例如,运行迁移,忘记回滚迁移,然后在提交前删除迁移文件),我可以按如下方式重现丢失的迁移:
- 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)
. - 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
) - Check your migration status and rollback (
rake db:migrate:status; rake db:rollback; rake db:migrate:status;
)
- 返回 git 历史以获取 schema.rb 文件的副本并保存在 git repo (
git log; git checkout xxxxxx; cp schema.rb ~/schema_old.rb, git checkout master)
. - 对两个文件运行差异,并将迁移命令复制到与缺少的迁移 ID (
diff schema.rb ~/schema_old.rb > migration_file.rb; vi migration_file.rb
)匹配的迁移文件中 - 检查您的迁移状态和回滚 (
rake db:migrate:status; rake db:rollback; rake db:migrate:status;
)
回答by mikeryz
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.
假设这些实际上是在数据库上运行的迁移版本,您应该很好地回滚。
回答by Whit Kemmey
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 表以删除与您没有文件的迁移对应的行。但是,如果您随后切换到具有不同迁移的另一个分支,这将导致问题。