【问题标题】:What is the preferred way to manage schema.rb in git?在 git 中管理 schema.rb 的首选方法是什么?
【发布时间】:2009-04-10 14:48:08
【问题描述】:

我不想将schema.rb 添加到.gitignore,因为我希望能够从该文件加载新的数据库架构。但是,将其签入会导致各种虚假冲突,而新的db:migrate:reset 可以轻松解决这些冲突。

基本上我想要一种方法:

  1. 将 schema.rb 保存在存储库中,用于部署时数据库设置
  2. 将 schema.rb 保留在 '.gitignore' 中以用于一般开发

会有一两个人负责更新schema.rb并知道它是正确的。

有没有办法让我的蛋糕也吃掉?

【问题讨论】:

  • 为什么会有冲突?其他开发者有不同的架构吗?
  • 开发者 A 添加一个迁移,测试他的东西。开发人员 B 添加了另一个迁移,测试他的东西。我合并了他们两个。至少它在 schema.rb 的 :version 上发生冲突。
  • db:migrate:resetdestroy 你的所有数据不好吗?
  • @morefromalan 真的,冲突的问题是懒惰的“其他人”,他们甚至不会在提交文件之前解决冲突。我想这可以为人事问题提供技术解决方案,但至少它有效。 :)

标签: ruby-on-rails git workflow schema.rb


【解决方案1】:

恐怕您正在寻找的神奇解决方案不存在。此文件通常在版本控制中进行管理,然后对于版本行上的任何冲突,只需选择两个日期中的较晚日期。只要您还运行所有相关的迁移,就不会以这种方式不同步。如果两个开发人员对 schema.rb 的相似区域进行了修改,并且除了版本之外您还遇到了冲突,那么您将面临正常的合并冲突解决方案,但在我看来,这些通常很容易理解和解决。希望对大家有所帮助!

【讨论】:

  • schema.rb 忽略了。你是对的,没有神奇的解决方案。任何依赖于文件的东西有时会被忽略,有时不会有各种问题。我希望这以后不会咬我。
【解决方案2】:

您可以做的另一件事是使用:

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

这会将文件保留在存储库中,但不会跟踪更改。您可以随时使用以下方式切换跟踪:

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

【讨论】:

  • 我喜欢这个解决方案。我的问题是我会经常在多个分支中进行迁移,并且列的顺序在开发人员之间是乱序的(可能只是 MySQL 的问题?列不应该有顺序。)唯一的问题是记住转它在主分支中重新打开。
【解决方案3】:

对我来说真正有效的是删除和 .gitignore schema.rb,然后在每个开发人员 rake db:migrate 时为他们重新生成它。

您仍然可以实现您想要的目标,而无需从 0 迁移并冒着多年前迁移失败的风险,只需定期对迁移进行“汇总”即可。你可以这样做:

  1. 使用rake db:migrate 运行所有未完成的迁移
  2. schema.rb 的内容放入ActiveRecord::Schema.define 块中
  3. 将其粘贴到 def up 内的 initial_schema 迁移中(覆盖已经存在的内容)
  4. 删除所有其他迁移

现在您的 initial_schema 迁移是您新系统的起点,您不必担心schema.rb 中可能无法正确解决的冲突。这并不神奇,但它确实有效。

【讨论】:

  • Tom 和@otto - 我认为你应该保留迁移。而且,如果 Schema.db 的点是迁移序列的替代品——由于某种原因可能容易出错——那么从一系列迁移中创建一个等效的 schema.db 是违背目的的。如果您想生成自己的 - 为什么不使用任何 DBMS 功能将架构导出为 .SQL?
  • 我不确定我是否遵循。 schema.rb(不是 .db)在 Rails 内部用于设置测试数据库并进行重置。简单地导出到 sql 并不能解决任何问题。保持多年的迁移价值也是行不通的。由于各种原因,经过多年的更改和数百次迁移,应用程序并不总是从 0 迁移。
  • 我不会这样做。在代码审查中看到对 db/schema.rb 的更改很有价值。
  • 有价值与否,说“不要那样做”并不能回答所提出的问题。
  • @MattyB 我不明白为什么对 db/schema.rb 的更改在代码审查中很有价值。这些变化告诉你什么是迁移不会看到的?
【解决方案4】:

在预提交 git 挂钩中执行 rake db:dump 就足够了吗?

以下不一定能解决 (1) 或 (2),但它可能会解决合并问题,然后 (1) 和 (2) 可能会消失。

【讨论】:

  • 并非如此,因为当您创建迁移并运行 db:migrate 时,您会自动获得 db:dump 并更新 schema.rb。问题在于,在日常开发中,每个人都在以某种方式更改数据库,最终您在生成的文件中遇到了冲突。
【解决方案5】:

不要使用.gitignore,而是使用单独的分支:Develop 省略 schema.rbTestDeploy,其中包括 schema.rb。仅在 Develop 分支中进行代码更改,切勿从 Test 合并到 Develop。将schema.rb 保存在单独的分支中:

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

在 Git 中,分支是指向文件内容集合的指针,因此它们可以包含或排除特定文件以及跟踪文件版本。这使它们成为构建特定工作流程的灵活工具。

【讨论】:

  • 这是否意味着 git merge develop 从 test 或 deploy 进行合并提交,而不是总是能够快速前进?我喜欢这个想法,但我还没有 100% 了解它是如何工作的。
  • 嗨,奥托。您的开发人员会在推回您的集成存储库之前提取您最新的 Master,因此您的合并应该是快进的(除非它们之间存在未解决的冲突)。测试和部署应该只是你的仓库中的 Master + Schema 或开发人员的 Develop + Local Schema。
  • 恕我直言,治疗比这里的疾病更糟糕。我已经尝试过 git 工作流程,其中分支中有不同的文件,而且从来不值得麻烦。我敢肯定,在某些情况下,像这样的强硬方法是必要的,但管理 schema.rb 不是这样。
【解决方案6】:

您可以定义合并策略。 我找到了这个解决方案,但不记得出处了

[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)'"

把这个“某处”和

git-config --global core.attributesfile "somewhere"
【解决方案7】:

我构建了一个 gem 来解决这个问题。

它对列、索引名称和外键进行排序,删除多余的空格并运行 Rubocop 进行一些格式化以统一 schema.rb 文件的输出。

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

将其添加到 Gemfile 后,您只需像往常一样运行 rake db:migraterake db:schema:dump

【讨论】:

    【解决方案8】:
    1. 提交schema.rb 文件。
    2. 运行 git pull(或继续你正在做的事情)

    每次迁移数据库时,schema.rb 文件都会更新并出现在git status 中。在处理某事并偶尔执行git pull 时,这可能很烦人,因为您必须在拉取解决冲突之前提交schema.rb 文件。这意味着每次迁移数据库时,都需要提交schema.rb文件。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2022-08-10
      • 1970-01-01
      • 1970-01-01
      • 2010-10-10
      • 2010-10-11
      • 2011-10-18
      • 1970-01-01
      相关资源
      最近更新 更多