2015-09-20 17 views
20

他のdjangoデベロッパーがどのようにして複数のコードブランチを管理しているのか不思議です。djangoのマイグレーション - 複数のdevブランチを持つワークフロー

次のように私の問題がある: - 私たちは、Djangoの移行(そのうちのいくつかのフィールドを変更すること、またはそれらを完全に削除する) で、gitの中でそれらのいくつかを、複数の機能ブランチを持っている - 私は(git checkout some_other_branchと)枝を切り替えるときに、データベース新しいコードが常に反映されるわけではないので、dbテーブルの列がもう存在しない「ランダムな」エラーが発生します。

今、dbを落として再作成しますが、作業を再開するためにダミーデータを再作成する必要があります。私は備品を使うことができますが、データがどこに行くのかを把握する必要があります。ちょっと面倒です。

このユースケースをうまく処理する方法はありますか?私はpost-checkout gitフックスクリプトが必要な移行を実行できると思っていますが、移行ロールバックが可能であるかどうかわかりません。

+2

@ eliot-berriotはほとんどのシナリオをカバーしていると思います。実際に私は、私は提案を示唆して、この記事を書くために、この問題に触発されました:[何が本当にDjangoの移行についての私を悩ます](https://cheesecakelabs.com/blog/really-annoys-django-migrations/?utm_source=stackoverflow&utm_medium= bernardo-question&utm_campaign = blog%20&utm_content = what-really-annoys-me-about-django-migrations)。そして、このlibをpost-checkout gitフックの提案で開始しました:[django-nomad](https://github.com/CheesecakeLabs/django-nomad)。どう思いますか? – bsmaniotto

答えて

11

移行ロールバックが可能で、通常はdjangoによって自動的に処理されます。あなたがpython manage.py makemigrations myappを実行する場合

class MyModel(models.Model): 
    pass 

は、それが最初の移行スクリプトを生成します。

次のようなモデルを考えます。 python manage.py migrate myapp 0001を実行して、この初期移行を適用できます。

その後、あなたのモデルにフィールドを追加する場合:

class MyModel(models.Model):  
    my_field = models.CharField() 

次に新しい移行を再生成し、それを適用し、あなたはまだ戻って初期状態に戻ることができます。 python manage.py migrate myapp 0001を実行すると、ORMが後方に移動し、新しいフィールドがになります。

データの移行を処理するのは、前方および後方のコードを記述する必要があるためです。 python manage.py makemigrations myapp --empty経由で作成された空の移行、 考慮すると、あなたのようなものになってしまいます:純粋なデータ・ロードの移行の場合

# -*- coding: utf-8 -*- 
from __future__ import unicode_literals 

from django.db import models, migrations 

def forward(apps, schema_editor): 
    # load some data 
    MyModel = apps.get_model('myapp', 'MyModel') 

    while condition: 
     instance = MyModel() 
     instance.save() 

def backward(apps, schema_editor): 
    # delete previously loaded data 
    MyModel = apps.get_model('myapp', 'MyModel') 

    while condition: 
     instance = MyModel.objects.get(myargs) 
     instance.delete() 

class Migration(migrations.Migration): 

    dependencies = [ 
     ('myapp', '0003_auto_20150918_1153'), 
    ] 

    operations = [ 
     migrations.RunPython(forward, backward), 
    ] 

、あなたは通常、後方移動を必要としません。 スキーマを変更して既存の行を更新するときは、
(列内のすべての値をslugに変換する場合と同じように)の場合、通常、後方ステップを記述する必要があります。

私たちのチームでは、衝突を避けるために同じモデルで同時に作業することを避けています。 同じ番号(例:0002)を持つ2つの移行が作成された場合は、 の名前を変更してその順番を変更しても適用されます( のdependencies属性を更新することを忘れないでください)。あなたの新しい注文への移行クラス)。

あなたはさまざまな機能で同時に同じモデルフィールドに取り組んで終わる場合は、 あなたはまだトラブルになるだろうが、それはかもしれない、これらの機能が関係していることを意味し、単一の分岐で一緒 を処理する必要があります。

はのgit - フックの部分については、それはブランチmybranch であなたのアールと仮定すると、何かを書くことはおそらく可能ですし、別の機能ブランチmyfeatureチェックアウトする:

  1. をすぐ切り替える前に、あなたはのリストをダンプ 一時ファイル次にmybranch_database_state.txt
  2. に現在適用されている移行、バックmybranchをチェックする際に任意の
  3. はその後、あなたはあなたのを再適用した場合、あなたは、myfeature分岐マイグレーションを適用します以前のデータベース状態 ダンプファイルを探してください。

しかし、それは私には少しハックようで、おそらく適切にすべてのシナリオを処理するのには本当に難しいだろう。彼らの移行の競合の取り扱いなど リベース、マージ、チェリーピッキング、

起こることは私にとっては簡単です。

4

私はこれに良い解決策を持っていないが、私は痛みを感じます。

ポスト・チェックアウト・フックは手遅れになります。あなたはブランチAであり、あなたが分岐Bをチェックアウトし、BがAよりも少ないの移行を持っている場合は、ロールバック情報は、Aのみで、チェックアウト前を実行する必要があります。

バグの起源を見つけるためにしようと、いくつかのコミットの間でジャンプするとき、私は、この問題をヒット。私たちのデータベース(開発トリムでさえ)は巨大なので、落として再作成するのは実用的ではありません。

私はgitのチェックアウトのラッパー想像しています:あなたのINSTALLED_APPS

  • のそれぞれについて、最新の移行がそれぞれのためにそこに最新の移行
  • を要求されたブランチに見えると指摘し

    1. ノート#1の移行が#2よりも先に行われている場合、#2で最も高い移行に移行する
    2. 新しいブランチを確認してください。
    3. #2の移行がすべてのアプリ#1の広告、前に移動

    プログラミングの簡単な問題!

  • 関連する問題