Git 분기 및 Rails 마이그레이션 작업 방법
저는 꽤 많은 git 지점이 있는 레일스 앱에서 작업하고 있으며 그 중 많은 부분이 DB 마이그레이션을 포함하고 있습니다.주의를 기울이려 하지만 때때로 마스터의 코드 조각이 다른 분기에서 제거/이름 변경된 열을 요청합니다.
깃 브랜치를 DB 상태와 "커플링"할 수 있는 좋은 해결책은 무엇입니까?
이 "국가"들은 실제로 무엇일까요?
크기가 몇 GB라면 데이터베이스를 복제할 수 없습니다.
합병하면 어떻게 될까요?
솔루션이 noSQL 데이터베이스로도 변환됩니까?
현재 MySQL, mongodb, redis를 사용하고 있습니다.
편집: 매우 중요한 점을 언급하는 것을 잊어버린 것 같습니다. 개발 환경에만 관심이 있고 대규모 데이터베이스(크기는 몇 GB)에 관심이 있습니다.
분기에서 새 마이그레이션을 추가할 때 실행rake db:migrate
그리고 두 가지 모두를 실행할 것을. db/schema.rb
이렇게 하면 개발 중에 다른 마이그레이션 집합이 있는 다른 브랜치로 전환하여 간단히 실행할 수 있습니다.rake db:schema:load
.
이렇게 하면 전체 데이터베이스가 다시 생성되고 기존 데이터가 손실됩니다.
매우 신중하게 운영하는 지점 하나에서만 운영을 실행할 수 있으므로 이 단계는 해당되지 않습니다(단, 실행).rake db:migrate
거기서 늘 그렇듯).그러나 개발 중에 스키마에서 데이터베이스를 다시 만드는 것은 큰 문제가 되지 않아야 합니다.rake db:schema:load
할 거다.
대규모 데이터베이스를 쉽게 복제할 수 없는 경우 일반 마이그레이션 도구를 사용하는 것이 좋습니다.간단한 프로세스를 원한다면 다음과 같이 하는 것이 좋습니다.
- 분기를 전환하기 전에 롤백(
rake db:rollback
분기점 이전의 상태로 이동합니다.그 다음 분기 전환 후 실행db:migrate
. 이것은 수학적으로 옳습니다. 그리고 당신이 글을 쓰는 한.down
대본, 잘 될 겁니다. - 브랜치를 전환하기 전에 이 작업을 수행하는 것을 잊어버린다면 일반적으로 안전하게 다시 전환하고 롤백하고 다시 전환할 수 있기 때문에 워크플로우로서 가능하다고 생각합니다.
- 서로 다른 분기의 마이그레이션 간에 종속성이 있는 경우...잘 생각해 보셔야 할 것 같아요
서로 다른 마이그레이션을 포함하는 분기 간 전환을 위해 작성한 스크립트는 다음과 같습니다.
https://gist.github.com/4076864
말씀하신 모든 문제를 해결할 수는 없겠지만 지점 이름을 지정하면 다음과 같습니다.
- 지정된 분기에 없는 현재 분기의 마이그레이션 롤백
- db/schema.rb 파일의 변경 내용을 삭제합니다.
- 지정된 분기를 체크아웃합니다.
- 지정된 분기에 존재하는 새 마이그레이션 실행
- 테스트 데이터베이스 업데이트
저는 저희 프로젝트에서 항상 수동으로 이 작업을 수행하고 있기 때문에 프로세스를 자동화하면 좋겠다고 생각했습니다.
분기별 데이터베이스 분리
날 수 있는 유일한 방법입니다.
2017년 10월 16일 업데이트
저는 꽤 오랜 시간이 지난 후에 이 문제로 돌아와 몇 가지 개선을 했습니다.
- 다른 네임스페이스 레이크 작업을 추가하여 분기를 생성하고 데이터베이스를 한 번에 복제합니다.
bundle exec rake git:branch
. - 마스터에서 복제하는 것이 항상 당신이 원하는 것은 아니라는 것을 이제 깨달았습니다. 그래서 저는 더 명확하게 말씀드렸습니다.
db:clone_from_branch
작업은 a를 갖습니다.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
다음은 분기 간에 데이터베이스를 쉽게 복제하는 레이크 작업입니다.이것은 필요합니다.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와 모든 마이그레이션이 모든 개발자에 의해 체크인되었는지 확인합니다.
운영 환경에 배포하려면 한 사람/기계가 있어야 합니다.이 기계를 병합 기계라고 부르자.변경 사항을 병합 시스템으로 풀링하면 schema.rb에 대한 자동 병합이 실패합니다.별 문제 없습니다.schema.rb의 이전 내용이 무엇이든 내용을 대체하면 됩니다(사용할 경우 복사본을 옆에 두거나 github에서 가져올 수 있습니다...).
여기에 중요한 단계가 있습니다.이제 모든 개발자의 마이그레이션을 db/migrate 폴더에서 사용할 수 있습니다.번들 실행 레이크 db:migrate를 실행합니다.그러면 병합 기계의 데이터베이스가 모든 변경 사항과 동등한 수준으로 제공됩니다.schema.rb도 재생성됩니다.
변경사항을 모든 리포지토리(원격 및 개인)에 커밋하고 밀어 넣습니다.당신은 끝나야 합니다!
이것이 제가 한 일이고 저는 모든 기본 사항을 다 포함했는지 확신할 수 없습니다.
개발 중(postgresql 사용):
- sql_dump db_name > tmp/branch1.sql
- git 체크아웃 지점2
- dropdbdb_name
- createdbdb_name
- psql db_name < tmp/ branch2.sql # (이전 분기 스위치에서)
이는 약 50,000개의 기록을 가진 데이터베이스의 레이크 유틸리티보다 훨씬 빠릅니다.
운영을 위해 마스터 분기를 신성불가침으로 유지하고 모든 마이그레이션을 체크인할 경우 shema.rb가 적절하게 병합됩니다.표준 업그레이드 절차를 따릅니다.
분기별로 "db 환경"을 보존하려고 합니다.다른 인스턴스를 가리키기 위해 번짐/깨끗한 스크립트를 살펴봅니다.db 인스턴스가 부족한 경우 스크립트가 임시 인스턴스를 종료하도록 설정하여 새 분기로 전환할 때 이미 설치되어 있고 스크립트 이름만 변경하면 됩니다.DB 업데이트는 테스트를 실행하기 직전에 실행되어야 합니다.
도움이 되길 바랍니다.
나는 당신이 여기서 먹고 있는 피타를 완전히 경험합니다.생각해보니 진짜 문제는 모든 지점이 특정 지점을 롤백할 수 있는 코드를 가지고 있지 않다는 것입니다.저는 장고계라서 갈퀴를 잘 모릅니다.나는 이주자들이 분기되지 않는 그들만의 레포(git-sub module, 최근에 알게 된 git-sub module)에 살고 있다는 생각을 가지고 놀고 있습니다.그렇게 하면 모든 지점이 모든 이동을 하게 됩니다.끈적거리는 부분은 각 지점이 그들이 신경 쓰는 마이그레이션에만 국한되도록 하고 있습니다.이를 수동으로 추적/추적하면 오류가 발생하기 쉽습니다.그러나 이를 위해 만들어진 마이그레이션 도구는 없습니다.그것이 제가 앞으로 나아갈 길이 없는 지점입니다.
다음 두 가지 옵션 중 하나를 제안합니다.
옵션1
- 데이터 입력
seeds.rb
. 좋은 옵션은 FactoryGirl/Fabrication gem을 통해 시드 데이터를 생성하는 것입니다.이렇게 하면 데이터가 코드와 동기화되어 있고 공장이 열 추가/제거와 함께 업데이트된다고 가정할 수 있습니다. - 한 분기에서 다른 분기로 전환한 후 실행
rake db:reset
, 데이터베이스를 효과적으로 삭제/creates/seeds합니다.
옵션2
항상 실행하여 데이터베이스의 상태를 수동으로 유지합니다.rake db:rollback
/rake db:migrate
지점 체크아웃 전/후주의해야 할 점은 모든 마이그레이션을 되돌릴 수 있어야 한다는 것입니다. 그렇지 않으면 이 작업이 작동하지 않습니다.
깃 풀을 수행하는 경우 풀을 통해 들어온 마이그레이션의 영향을 받는 최신 스키마가 이미 있지만 데이터베이스 테이블이 업데이트되지 않을 수 있습니다.
따라서 끌어 올린 후 마이그레이션을 실행해야 하지만 종종 변경됩니다.db/schema.rb
끌어다 놓고 마이그레이션하는 작업만 수행했다면 결과 스키마 변경은 기술적으로 사용자의 것이 아니기 때문에 사용자가 책임져야 할 이유가 없습니다. 결과 스키마 변경은 사용자의 것이 아니기 때문에 결국 외부/잘못되었을 수 있습니다.
스키마 차이를 재설정하는 것이 가장 합리적입니다.
다음은 새 분기를 생성하기 전에 수행해야 할 작업에 대한 단계별 버전입니다.
- 상위/기본 분기로 전환
- 최신 코드 꺼내기
- 달려.
bundle exec rake db:migrate
최신 정보를 제공합니다.schema.rb
현지에서 철하다 - 하라.
git checkout db/schema.rb
가 가져온 변화를 버리다db:migrate
있으면 - 새 분기를 생성하고 분기로 전환합니다.
- 다른 지점으로 전환하기 전에 변경 사항을 확인하십시오.
여기서 각색
개발 환경에 대해:
당신은 함께 일을 해야 합니다.rake db:migrate:redo
당신의 스크립트가 가역적인지 테스트하기 위해, 그러나 항상 명심해야 합니다.seed.rb
데이터 인구와 함께.
git로 작업하는 경우 seed.rb는 마이그레이션 변경과 함께 변경되어야 하며 실행은db:migrate:redo
시작을 위해 (다른 기계나 새 데이터베이스에 새 개발을 위한 데이터를 로드)
""변경"을 제외하고, 당신의 업 및 다운 방식으로 당신의 코드는 항상 이 순간과 0에서 시작할 때 "변경"에 대한 시나리오를 포함합니다.
언급URL : https://stackoverflow.com/questions/4735058/how-to-work-with-git-branches-and-rails-migrations
'it-source' 카테고리의 다른 글
JQuery: 크기 조정이 완료된 후에만 크기 조정 이벤트를 호출하는 방법은 무엇입니까? (0) | 2023.11.02 |
---|---|
시간 성분이 없는 NSD 날짜 비교 (0) | 2023.11.02 |
실행 중인 모든 도커 컨테이너를 다시 시작하는 명령? (0) | 2023.11.02 |
MS Word 문서에서 구문 강조 표시 (0) | 2023.11.02 |
포스트렌더 "플리커"를 제거하는 방법은? (0) | 2023.11.02 |