私はRailsかなりの数のgitブランチを持つアプリに取り組んでおり、それらの多くはdb移行を含んでいます。 /別のブランチで名前を変更しました。
gitブランチをDB状態と「結合」するための素敵なソリューションは何でしょうか?
これらの「状態」は実際にはどうなりますか?
数GBのサイズのデータベースを複製することはできません。
そして、マージで何が起こるべきですか?
ソリューションはnoSQLデータベースにも変換されますか?
現在、MySQL、mongodb、およびredisを使用しています
編集:私は非常に重要な点に言及するのを忘れたように見えます。私は開発環境にのみ興味がありますが、大きなデータベース(数GBのサイズ)を使用します。
ブランチに新しい移行を追加する場合、rake db:migrate
を実行し、両方の移行をコミットしますanddb/schema.rb
これを行うと、開発中に、異なる移行セットを持つ別のブランチに切り替えて、rake db:schema:load
を実行することができます。
データベース全体を再作成すると、既存のデータは失われますになります。
たぶん、あなたは非常に注意している1つのブランチからのみ本番を実行したいので、これらの手順はそこでは適用されません(そこでrake db:migrate
を実行するだけです)。しかし、開発では、スキーマからデータベースを再作成することは大したことではありません。これは、rake db:schema:load
が行うことです。
すぐに再現できない大きなデータベースがある場合は、通常の移行ツールを使用することをお勧めします。簡単なプロセスが必要な場合、これがお勧めです。
rake db:rollback
)します。次に、ブランチを切り替えた後、db:migrate
を実行します。これは数学的には正しく、down
スクリプトを記述している限り機能します。以下は、異なる移行を含むブランチ間を切り替えるために書いたスクリプトです。
https://Gist.github.com/4076864
あなたが言及したすべての問題を解決するわけではありませんが、ブランチ名を指定すると:
私たちのプロジェクトでは常にこれを手動で行っているので、プロセスを自動化するのは良いことだと思いました。
それが唯一の飛行方法です。
しばらくしてからこれに戻り、いくつかの改善を行いました。
bundle exec rake git:branch
を使用して、ブランチを作成し、データベースを一度に複製する別の名前空間のrakeタスクを追加しました。db:clone_from_branch
タスクがSOURCE_BRANCH
およびTARGET_BRANCH
環境変数を取ることをより明確にしました。 git:branch
を使用すると、現在のブランチがSOURCE_BRANCH
として自動的に使用されます。config/database.yml
そして、あなたにとって使いやすくするために、database.yml
ファイルを更新して、現在のブランチに基づいてデータベース名を動的に決定する方法を次に示します。
<%
database_prefix = 'your_app_name'
environments = %W( development test )
current_branch = `git status | head -1`.to_s.gsub('On branch ','').chomp
%>
defaults: &defaults
pool: 5
adapter: mysql2
encoding: utf8
reconnect: false
username: root
password:
Host: localhost
<% environments.each do |environment| %>
<%= environment %>:
<<: *defaults
database: <%= [ database_prefix, current_branch, environment ].join('_') %>
<% end %>
lib/tasks/db.rake
これは、あるブランチから別のブランチにデータベースを簡単に複製するためのRakeタスクです。これは、SOURCE_BRANCH
およびTARGET_BRANCH
環境変数を取ります。 @ spalladino のタスクに基づいています。
namespace :db do
desc "Clones database from another branch as specified by `SOURCE_BRANCH` and `TARGET_BRANCH` env params."
task :clone_from_branch do
abort "You need to provide a SOURCE_BRANCH to clone from as an environment variable." if ENV['SOURCE_BRANCH'].blank?
abort "You need to provide a TARGET_BRANCH to clone to as an environment variable." if ENV['TARGET_BRANCH'].blank?
database_configuration = Rails.configuration.database_configuration[Rails.env]
current_database_name = database_configuration["database"]
source_db = current_database_name.sub(CURRENT_BRANCH, ENV['SOURCE_BRANCH'])
target_db = current_database_name.sub(CURRENT_BRANCH, ENV['TARGET_BRANCH'])
mysql_opts = "-u #{database_configuration['username']} "
mysql_opts << "--password=\"#{database_configuration['password']}\" " if database_configuration['password'].presence
`mysqlshow #{mysql_opts} | grep "#{source_db}"`
raise "Source database #{source_db} not found" if $?.to_i != 0
`mysqlshow #{mysql_opts} | grep "#{target_db}"`
raise "Target database #{target_db} already exists" if $?.to_i == 0
puts "Creating empty database #{target_db}"
`mysql #{mysql_opts} -e "CREATE DATABASE #{target_db}"`
puts "Copying #{source_db} into #{target_db}"
`mysqldump #{mysql_opts} #{source_db} | mysql #{mysql_opts} #{target_db}`
end
end
lib/tasks/git.rake
このタスクは、現在のブランチ(マスターなど)からgitブランチを作成し、チェックアウトして、現在のブランチのデータベースを新しいブランチのデータベースに複製します。なめらかなAFです。
namespace :git do
desc "Create a branch off the current branch and clone the current branch's database."
task :branch do
print 'New Branch Name: '
new_branch_name = STDIN.gets.strip
CURRENT_BRANCH = `git status | head -1`.to_s.gsub('On branch ','').chomp
say "Creating new branch and checking it out..."
sh "git co -b #{new_branch_name}"
say "Cloning database from #{CURRENT_BRANCH}..."
ENV['SOURCE_BRANCH'] = CURRENT_BRANCH # Set source to be the current branch for clone_from_branch task.
ENV['TARGET_BRANCH'] = new_branch_name
Rake::Task['db:clone_from_branch'].invoke
say "All done!"
end
end
あとは、bundle exec git:branch
を実行し、新しいブランチ名を入力して、ゾンビの殺害を開始するだけです。
おそらく、開発データベースが大きすぎるというヒントとしてこれを使用する必要がありますか?開発にdb/seeds.rbと小さなデータセットを使用できる場合、現在のブランチのschema.rbとseeds.rbを使用することで問題を簡単に解決できます。
それはあなたの質問が開発に関係していると仮定しています。運用環境でブランチを定期的に切り替える必要がある理由は想像できません。
私は同じ問題に苦労していました。ここに私の解決策があります:
Schema.rbとすべての移行の両方がすべての開発者によってチェックインされていることを確認してください。
本番環境への展開には1人/マシンが必要です。このマシンをマージマシンと呼びましょう。変更がマージマシンにプルされると、schema.rbの自動マージは失敗します。問題ありません。 schema.rbの以前のコンテンツが何であれ、コンテンツを置き換えるだけです(コピーを保存するか、使用する場合はgithubから取得できます...)。
ここに重要なステップがあります。これで、すべての開発者からの移行がdb/migrateフォルダーで利用可能になります。先に進んでbundle exec rake db:migrateを実行します。すべての変更と同等のマージマシン上のデータベースを使用します。また、schema.rbも再生成します。
変更をコミットして、すべてのリポジトリ(リモートであるリモートおよび個人)にプッシュします。これで完了です!
これは私がやったことであり、すべてのベースをカバーしたかどうかはわかりません:
開発中(postgresqlを使用):
これは、約5万件のレコードを持つデータベースのrakeユーティリティよりもはるかに高速です。
本番環境では、masterブランチをsacrosanctとして維持し、すべての移行をチェックインし、shema.rbを適切にマージします。標準のアップグレード手順を実行します。
私はあなたがここで持っているピタを完全に体験します。私が考えているように、本当の問題は、すべてのブランチに特定のブランチをロールバックするコードがないことです。私はDjangoの世界にいるので、熊手がよくわからない。移行は分岐しない独自のリポジトリにあるという考えをいじっている(git -サブモジュール、私は最近学びました。そのように、すべてのブランチはすべての移行を持っています。スティッキーな部分は、各ブランチが関心のある移行のみに制限されていることを確認しています。エラーが発生しやすいですが、このための移行ツールはどれも作成されていません。
ブランチごとに「db環境」を保持する必要があります。汚れ/クリーンスクリプトを見て、異なるインスタンスをポイントします。 dbインスタンスを使い果たした場合、スクリプトに一時インスタンスをスピンオフさせて、新しいブランチに切り替えたときに既に存在し、スクリプトによって名前を変更するだけでよいようにします。 DB更新は、テストを実行する直前に実行する必要があります。
お役に立てれば。
次の2つのオプションのいずれかをお勧めします。
seeds.rb
に配置します。素敵なオプションは、FactoryGirl/Fabrication gemを介してシードデータを作成することです。この方法により、列の追加/削除とともにファクトリが更新されると想定した場合に、データがコードと同期していることを保証できます。rake db:reset
を実行します。これにより、データベースが効果的にドロップ/作成/シードされます。ブランチチェックアウトの前後に常にrake db:rollback
/rake db:migrate
を実行することにより、データベースの状態を手動で維持します。注意点は、すべての移行を元に戻す必要があることです。そうしないと機能しません。
開発環境:
rake db:migrate:redo
スクリプトがリバーシブルかどうかをテストしますが、常にseed.rb
データ入力。
Gitを使用している場合、seed.rbは移行の変更に伴い変更され、db:migrate:redo
開始(他のマシンまたは新しいデータベースでの新しい開発のためのデータのロード)
「変更」とは別に、アップとダウンのメソッドを使用すると、コードは常に、この瞬間とゼロから開始する「変更」のシナリオをカバーします。