【Django】makemigrationsが競合して困った話と対処法

Django

こんにちは、かつコーチです。

チーム開発でDjangoを使っていると、ある日突然マイグレーションが動かなくなることがあります。
筆者はチームで開発していたとき、自分のブランチでgit pullした直後にmigrateを実行したら、見たことのないエラーで画面が埋め尽くされて焦った経験があります。

この記事では、複数人開発でとくに発生しやすいマイグレーションの競合について、実際に起きがちなエラーメッセージを引用しながら原因と対処法を解説します。

マイグレーション競合はなぜ起きるのか

マイグレーションファイルは「連番の履歴」である

Djangoのマイグレーションとは、モデルの変更内容をDBに反映するための「変更履歴ファイル」です。
0001_initial.py0002_xxx.pyのように連番で管理されており、Djangoはこの順番通りに適用していく前提で動いています。

複数人が同時に同じアプリでマイグレーションを作ると起きる

問題は、複数人が同じタイミングで同じアプリのマイグレーションを追加したときに起きます。

例えばAさんとBさんが同時にblogアプリのモデルを変更し、それぞれの手元でmakemigrationsを実行したとします。
どちらの手元でも「前のマイグレーションの次は自分の変更」という認識になるため、Aさんは0005_add_author.py、Bさんも同じく0005_add_thumbnail.pyのように、同じ番号のファイルが2つできてしまうのです。

先にpushした方が正になり、後からpullした方は自分の環境と履歴が食い違った状態になります。

よくあるつまずきポイント・エラー対処

Conflicting migrations detected

❌Before

git pullした後にmakemigrationsを実行すると、次のようなエラーが出ます。

CommandError: Conflicting migrations detected; multiple leaf nodes in the migration graph: (0005_add_thumbnail, 0005_add_author in blog).
To fix them run 'python manage.py makemigrations --merge'

これは「マイグレーションの履歴が枝分かれ(2つの最新地点=leaf nodeが存在)している」という意味です。
筆者はこのメッセージを見た瞬間、自分のモデル定義が壊れたのかと思い込みましたが、実際は履歴の分岐が原因で、モデル自体は正常でした。

✅After

Djangoが親切にも解決コマンドを教えてくれているので、その通りに実行します。

python manage.py makemigrations --merge

これを実行すると、2つの分岐をまとめるマージ用マイグレーション(例:0006_merge_20260831_1200.py)が自動生成されます。
中身を確認し、問題なければそのままmigrateを実行します。

python manage.py migrate

マージ後もmigrateでエラーが出るケース

マージしても、両方のマイグレーションが同じカラムを別々の方法で追加しているような場合、以下のようなエラーが出ることがあります。

django.db.utils.OperationalError: duplicate column name: thumbnail

これは、すでにAさんの変更でthumbnailカラムが追加されているDBに対して、Bさんのマイグレーションが同じカラムを再度追加しようとした場合に起きます。

✅After

この場合は自動マージに頼らず、以下の手順で手動整理するのが確実です。

  1. 重複している変更内容を関係者間で確認する
  2. 片方のマイグレーションファイルを削除、または--fakeオプションで「実行済み扱い」にする
# すでに手元のDBには反映済みの変更を、実行済みとして記録だけする
python manage.py migrate blog 0005_add_thumbnail --fake

--fakeは「DBには何もしないが、Djangoの管理台帳上は適用済みとして記録する」オプションです。
安易に使うとDBの実態とマイグレーション履歴がズレるため、内容を完全に理解した上でのみ使いましょう。

応用・一歩先の使い方

競合を未然に防ぐチーム開発のルール

競合そのものをゼロにはできませんが、発生頻度を下げる工夫はできます。

  • モデルを変更したら、その日のうちに makemigrations して早めにpushする
  • 大きな機能追加の前にチームで一声かけ、マイグレーションが重ならないタイミングを揃える
  • git pull直後は必ずshowmigrationsで状態を確認してから作業を始める
python manage.py showmigrations blog

このコマンドで、適用済み([X])・未適用([ ])のマイグレーションを一覧確認できます。

マージコミットを作ったらチームに共有する

--mergeで作られたマイグレーションファイルは、必ずコミットしてpushしましょう。
自分のローカルだけでマージを解決して満足してしまい、他のメンバーが再び同じ競合にぶつかる、というのはチーム開発でよくある事故です。

まとめ

この記事のポイント

  • マイグレーション競合は、複数人が同時に同じアプリの変更を加えたときに発生する
  • Conflicting migrations detectedが出たらmakemigrations --mergeで解決を試みる
  • カラム重複などマージで解決できない場合は--fakeオプションも選択肢になる
  • showmigrationsで現在の適用状況をこまめに確認する習慣が予防につながる

次に読むべき記事

マイグレーション自体の基本操作をおさらいしたい場合は、「makemigrations/migrateの基本:モデルをDBに反映する」の記事もあわせてご覧ください。

タグ: Django, 中級者向け, エラー解決

タイトルとURLをコピーしました