web-dev-qa-db-ja.com

gitでschema.rbを管理するための好ましい方法は何ですか?

schema.rb.gitignoreに追加したくないのは、そのファイルから新しいデータベーススキーマをロードできるようにするためです。ただし、チェックインしたままにしておくと、新しいdb:migrate:resetで簡単に解決できるあらゆる種類の偽の競合が発生します。

基本的に私は次の方法が必要です:

  1. デプロイ時のデータベース設定のために、schema.rbをリポジトリに保持します
  2. 一般的な開発のために、schema.rbを「.gitignore」に保持します

schema.rbを更新し、それが正しいことを知っている責任者は1人か2人です。

ケーキを持って食べる方法はありますか?

49
Otto

私にとって本当にうまくいったのは、schema.rbを削除して.gitignoreし、開発者がrake db:migrateしたときに開発者ごとに再生成することです。

定期的に移行の「ロールアップ」を行うだけで、0から移行したり、数年前から移行が失敗したりするリスクを冒すことなく、目的を達成できます。これは次の方法で実行できます。

  1. rake db:migrateを使用してすべての未処理の移行を実行します
  2. schema.rbブロックのActiveRecord::Schema.defineの内容を取得する
  3. def up内のinitial_schema移行に貼り付けます(すでに存在するものを上書きします)
  4. 他のすべての移行を削除します

これで、initial_schemaの移行が新しいシステムの開始点になり、正しく解決されない可能性のあるschema.rbの競合について心配する必要がなくなりました。それは魔法ではありませんが、機能します。

2
Tom Harris

あなたが探している魔法の解決策は存在しないのではないかと思います。このファイルは通常、バージョン管理で管理されます。バージョン行で競合が発生した場合は、2つの日付のうち遅い方を選択してください。関連するすべての移行も実行している限り、この方法で同期が外れることはありません。 2人の開発者がschema.rbの同様の領域に変更を加え、バージョンに加えて競合が発生した場合、通常のマージ競合の解決に直面しますが、私の意見では、これらは通常、理解と解決が容易です。これがお役に立てば幸いです。

21
Adam Alexander

あなたができるもう一つのことは使用することです:

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

これにより、ファイルはリポジトリに保持されますが、変更は追跡されません。次を使用して、いつでも追跡を切り替えることができます。

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

.gitignoreを使用する代わりに、別々のブランチを使用します:schema.rbDevelopを省略したTestschema.rbを含むDeploy。開発ブランチでのみコードを変更し、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では、ブランチはファイルコンテンツのコレクションへのポインターであるため、特定のファイルを含めたり除外したり、ファイルバージョンを追跡したりできます。これにより、特定のワークフローを構築するための柔軟なツールになります。

1
Paul

マージ戦略を定義できます。私はこの解決策を見つけましたが、ソースを覚えていません

[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"
1
andrea

私はこの問題を解決するために宝石を作りました。

列、インデックス名、外部キーを並べ替え、余分な空白を削除し、Rubocopを実行してフォーマットを行い、schema.rbファイルの出力を統合します。

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

それをGemfileに追加した後、通常のようにrake db:migrateまたはrake db:schema:dumpを実行するだけです。

1
jakeonrails

コミット前のgitフックでrakedb:dumpを実行するだけで十分でしょうか?

以下は、必ずしも(1)または(2)を修正するわけではありませんが、マージの問題を処理する可能性があり、その後、(1)および(2)がなくなる可能性があります。

1
dbrown0708
  1. schema.rbファイルをコミットします。
  2. Git pullを実行します(または実行していることを続行します)

データベースを移行するたびに、schema.rbファイルが更新され、git statusに表示されます。何かに取り組んでいて、時々git pullを実行する場合、競合を解決するためにプルする前にschema.rbファイルをコミットする必要があるため、これは煩わしい場合があります。これは、データベースを移行するたびに、schema.rbファイルをコミットする必要があることを意味します。

0
Chemist