Knowledge

マイグレーションのコンフリクトをなくすツール Migrapheの紹介

公開日:2026/07/06
技術ノウハウ・Tips設計・アーキテクチャ

チームで開発を進めていると、DBのマイグレーションで「同じ番号のファイルを2人が作った」「マージしたら順番が壊れた」といった衝突に遭遇したことはありませんか?
変更の中身はぶつかっていないのに、順番の付け方だけが原因で手が止まる。
これ、けっこうフラストレーション溜まりますよね。
そんなに頻度があるわけではないので放置してきたのですが、時々起こってしまって面倒な思いをしてきました。

AIの台頭で余裕ができたため、この課題を解決しようと作ったのがMigraphe(マイグレイフ)です。

Migrapheは、実行順を連番ではなく依存関係で決めるツールです。
各自が依存だけ書いて独立にファイルを足せるので、順番でぶつかることがありません。

マイグレーションがコンフリクトする原因

多くのツールは変更を「001002」の連番やタイムスタンプで並べ、その順に適用します。
これはこれで分かりやすいですが、チームで使うとこんなことが起きがちです。

  • 同じ番号のファイルが2つできてしまった
  • すでに適用済みのファイルの番号より小さい番号のファイルが、マージで後から入ってしまった

これらが起こると、どちらかのファイル名を変えたり、採番しなおしたりして、コンフリクトを解消しなければなりません。
また、レビュー時にどこまで本番に流していたかを頭の片隅に置いてレビューしなければ防げません。

これらの問題の原因は、すべての変更が意図せず順序という暗黙の依存関係でつながれていることです。

Migrapheなら採番のコンフリクトは起きない

Migrapheは実行順を「どのタスクのあとに実行したいか」という依存関係で決める設計です。 各マイグレーションでは、dependenciesに依存先を書きます。
すると、Migrapheが依存関係のグラフから自動で実行順を組み立てます。

# tasks/orders/create_orders.yaml
name: 注文テーブルを作成
dependencies:
  - users/create_users   # usersテーブルができてから実行したい
up: |
  CREATE TABLE orders (
    id BIGSERIAL PRIMARY KEY,
    user_id BIGINT NOT NULL REFERENCES users (id)
  );
down: |
  DROP TABLE IF EXISTS orders;

たとえば既存のusersテーブルに依存する「注文」「住所」「セッション」テーブルを、別々の開発者が開発する場合を考えます。
各自がやるのは、「usersに依存する」と書いたマイグレーションファイルを1枚置くこと。

採番方式であれば、誰が何番を使うかをあらかじめ決めておくか、マージ時に遅かった人のファイル名を修正してもらうかなどの考慮が必要です。
この依存関係を宣言する方式であれば、番号がないため衝突せずマージできます。

スキーマからドキュメントを自動でつくれる

Migrapheにはスキーマから成果物を生成する仕組みもあります。
たとえばテーブルやカラムをまとめたMarkdownドキュメントなら、設定にこう書いておけば標準のジェネレータから出力できます。

generators:
  - name: schema-docs
    type: postgresql-markdown   # スキーマをMarkdownドキュメント化(標準同梱)
    source:
      type: postgresql-schema
    output-dir: docs/schema
migraphe generate

生成物はこんな形です。
実行の手間はほぼないため、マイグレーションのたびに作り直すことも可能です。
自動で実行されるようにしておけば、ドキュメントがメンテされず古いまま、という問題も解決できます。

docs/schema/                 # output-dir で指定した場所
├── index.md                 # スキーマ概要
└── schema-docs/             # ジェネレータ名(generators[].name)
    └── public/              # スキーマ名
        └── tables/
            ├── users.md     # カラム・制約・インデックスの一覧
            └── orders.md

また、出力先は自由な場所に差し替えできますし、独自に出力プラグインを作成すれば、プロジェクト用のエンティティクラスなど好きな形式で吐き出すことも可能です。

ほかにできること

依存関係を明示する方式にしたおかげで、独立したタスクが判別できるようになり、それらを並列に実行できます。
接続先はDBやユーザーごとに定義が可能で、マイグレーションファイルごとに切り替えができます。
巻き戻し時も依存関係を見ていて、戻したいタスクに連なる一連のタスクもまとめて巻き戻す、ということが可能です。

導入と使い方

導入はmiseなら1行です。

mise use github:kakusuke/migraphe

主要コマンドはこれだけ。

migraphe status     # 適用状況を確認
migraphe up         # マイグレーションを適用
migraphe down <id>  # 指定タスクとその依存を巻き戻し
migraphe generate   # スキーマからドキュメントを生成
statusは適用済み(✓)と未適用を依存関係付きで表示します。

migraphe status の出力画面。左側に依存関係のツリーが描画され、各タスクの適用状況(✓=適用済み)と実行時間が一覧表示されている

まとめ

  • 連番では、それ自体が依存関係の表現になってしまう
  • Migrapheは依存関係を明示的に宣言する
  • Migrapheはスキーマからドキュメントも自動生成できる

良さそうに思えたら、ぜひ使ってみて、フィードバックをいただけたらありがたいです。


関連リンク

  • Migraphe リポジトリ(GitHub): https://github.com/kakusuke/migraphe
  • ユーザーガイド・サンプル: リポジトリ内の docs/sample/clisample/gradle
  • 対応プラグイン: PostgreSQL / MySQL / JDBC / JSON出力ジェネレータ
  • mise(インストールに利用するバージョンマネージャ): https://mise.jdx.dev

執筆者:S.T.(プロフィール)

まずはお気軽にご相談ください。
構想段階から最適な形を一緒に考えます。

あなたに最適な解決策を一緒に考えます。

Contact お問い合わせ

状況に応じた最適なご提案で、お客様の課題解決をサポートいたします