简体   繁体   English

在git中管理schema.rb的首选方法是什么?

[英]What is the preferred way to manage schema.rb in git?

I don't want to add schema.rb to .gitignore , because I want to be able to load a new database schema from that file. 我不想将schema.rb添加到.gitignore ,因为我希望能够从该文件加载新的数据库模式。 However, keeping it checked in is causing all sorts of spurious conflicts that are easily resolved by a fresh db:migrate:reset . 但是,保持签入是导致各种虚假冲突,可以通过新的db:migrate:reset轻松解决。

Basically I want a way to: 基本上我想要一种方法:

  1. Keep schema.rb in the repository for deploy-time database setup 将schema.rb保留在存储库中以进行部署时数据库设置
  2. Keep schema.rb in '.gitignore' for general development 将schema.rb保留在'.gitignore'中以进行常规开发

There would be one or two people responsible for updating schema.rb and knowing that it was correct. 将有一两个人负责更新schema.rb并知道它是正确的。

Is there a way I can have my cake and eat it, too? 有没有办法我可以吃蛋糕然后吃它?

I'm afraid the magic solution you're looking for does not exist. 我担心你所寻找的神奇解决方案不存在。 This file is normally managed in version control, then for any conflicts on the version line just choose the later of the two dates. 此文件通常在版本控制中进行管理,然后对于版本行上的任何冲突,只需选择两个日期中的较晚者。 As long as you're also running all of the associated migrations nothing should get out of sync this way. 只要您还运行所有相关的迁移,任何事情都不会以这种方式失去同步。 If two developers have caused modifications to a similar area of schema.rb and you get conflicts in addition to the version then you are faced with a normal merge conflict resolution, but in my opinion these are normally easy to understand and resolve. 如果两个开发人员对schema.rb的类似区域进行了修改,并且除了版本之外还会遇到冲突,那么您将面临正常的合并冲突解决方案,但在我看来,这些通常很容易理解和解决。 I hope this helps some! 我希望这会有所帮助!

One other thing you can do is use: 您可以做的另一件事是使用:

git update-index --assume-unchanged /path/schema.rb

This will keep the file in the repository but won't track changes. 这将使文件保留在存储库中,但不会跟踪更改。 you can switch the tracking anytime by using: 你可以随时使用以下方式切换跟踪:

git update-index --no-assume-unchanged /path/schema.rb

What has worked really well for me is to delete and .gitignore schema.rb and then have it regenerated for each developer when they rake db:migrate . 对我来说非常有用的是删除和.gitignore schema.rb ,然后在他们使用rake db:migrate时为每个开发人员重新生成它。

You can still achieve what you wanted without migrating from 0 and risking broken migrations from years ago by simply doing a "roll-up" of the migrations periodically. 通过简单地定期“迁移”迁移,您仍然可以实现所需的目标,而无需从0迁移,并且可能会在几年前破坏迁移的风险。 You can do this by: 你可以这样做:

  1. Run all outstanding migrations with rake db:migrate 使用rake db:migrate运行所有未完成的rake db:migrate
  2. Taking the contents of your schema.rb in the ActiveRecord::Schema.define block 获取ActiveRecord::Schema.define块中schema.rb的内容
  3. Paste it into your initial_schema migration inside def up (overwriting what's already there) 将其粘贴到def up initial_schema迁移中(覆盖已存在的内容)
  4. Delete all other migrations 删除所有其他迁移

Now your initial_schema migration is your starting point for new systems and you don't have to worry about conflicts in schema.rb that may not be resolved correctly. 现在,您的initial_schema迁移是新系统的起点,您不必担心schema.rb中可能无法正确解决的冲突。 It's not magical, but it works. 它并不神奇,但它确实有效。

You could define a merge strategy. 您可以定义合并策略。 I've found this solution, but dont remember the source 我找到了这个解决方案,但不记得来源

[merge "railsschema"]
name = newer Rails schema version
driver = "ruby -e '\n\
    system %(git), %(merge-file), %(--marker-size=%L), %(%A), %(%O), %(%B)\n\
    b = File.read(%(%A))\n\
    b.sub!(/^<+ .*\\nActiveRecord::Schema\\.define.:version => (\\d+). do\\n=+\\nActiveRecord::Schema\\.define.:version => (\\d+). do\\n>+ .*/) do\n\
      %(ActiveRecord::Schema.define(:version => #{[$1, $2].max}) do)\n\
    end\n\
    File.open(%(%A), %(w)) {|f| f.write(b)}\n\
    exit 1 if b.include?(%(<)*%L)'"

put this "somewhere" and 把这个“放在某处”

git-config --global core.attributesfile "somewhere"

I built a gem to solve this problem. 我建造了一个宝石来解决这个问题。

It sorts columns, index names and foreign keys, removes excess whitespace and runs Rubocop for some formatting to unify the output of your schema.rb file. 它对列,索引名和外键进行排序,删除多余的空格并运行Rubocop以进行某些格式化以统一schema.rb文件的输出。

https://github.com/jakeonrails/fix-db-schema-conflicts https://github.com/jakeonrails/fix-db-schema-conflicts

After you add it to your Gemfile you just run rake db:migrate or rake db:schema:dump like normal. 将它添加到您的Gemfile后,您只需运行rake db:migraterake db:schema:dump就像正常一样。

Would it be sufficient to do a rake db:dump in a pre-commit git hook? 在pre-commit git hook中执行rake db:dump是否足够?

The following won't necessarily fix (1) or (2), but it might take care of the merging issue, and then maybe (1) and (2) go away. 以下不一定会修复(1)或(2),但它可能会解决合并问题,然后可能(1)和(2)消失。

Instead of using .gitignore , use separate branches: Develop which omits schema.rb and Test and Deploy which include schema.rb . 而不是使用.gitignore ,使用单独的分支: Develop省略schema.rbTest and Deploy ,其中包括schema.rb Only make code changes in the Develop branches and never merge from Test into Develop . 只在Develop分支中进行代码更改,永远不会从Test合并到Develop Keep schema.rb in a separate branch: schema.rb保存在单独的分支中:

Developer A             
    Develop      --------             
    Local Schema          \           Your Repo
    Test                    --------->    Dev A
                            --------->    Dev B
Developer B               /               Master
    Develop      --------                 Schema
    Local Schema                          Test
    Test                                  Deploy

In Git, branches are pointers to collections of file contents, so they can include or exclude particular files as well as track file versions. 在Git中,分支是指向文件内容集合的指针,因此它们可以包含或排除特定文件以及跟踪文件版本。 This makes them flexible tools for building your particular workflow. 这使它们成为构建特定工作流程的灵活工具。

  1. Commit schema.rb file. 提交schema.rb文件。
  2. Run git pull (or continue with what you're doing) 运行git pull(或继续你正在做的事情)

Every time you migrate the database, the schema.rb file updates and appears in git status . 每次迁移数据库时, schema.rb文件都会更新并显示为git status When working on something and occasionally doing git pull , this can be annoying because you have to commit schema.rb file before pulling to resolve conflict. 在处理某些事情并偶尔进行git pull ,这可能很烦人,因为你必须提交schema.rb文件才能解决冲突。 This means that every time you migrate the database, you need to commit schema.rb file. 这意味着每次迁移数据库时,都需要提交schema.rb文件。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM