Fragments of verbose memory

冗長な記憶の断片 - Web技術のメモをほぼ毎日更新

Dec 24, 2025 - 日記

supabase db push はなぜ失敗するのか: マイグレーションの本質を理解する

supabase-migration-complete-guide cover image

supabase db push したら謎のエラーで失敗した」——Supabase でデータベース開発をしていると、一度は遭遇するトラブルです。このエラーの原因を追いかけることで、マイグレーションの本質が見えてきます。

本記事では、よくある3つの失敗パターンと、その背後にある「マイグレーション履歴の仕組み」を解説します。トラブル対処だけでなく、なぜそのような設計になっているのか、どう付き合っていくべきかを理解することで、安全な運用への道筋が見えてくるはずです。

Supabaseを使った開発を始めたばかりの方、AIツール(CursorSupabase MCP など)でスキーマ変更を行っている方に特におすすめの内容です。

突然のエラー: 何が起きたのか

開発中、ローカルで作成したマイグレーションを本番に適用しようとした時のことです。

$ supabase db push
Error: cannot apply migration 20240115120000_create_users_table.sql: 
relation "users" already exists

あるいは、こんなパターンも。

$ supabase db push
Error: migration 20240115120000 has already been applied

さらに厄介なのがこれ。

$ supabase db push
Error: migration history is not in sync with local migrations
Remote has migrations not found locally: 20240114090000

一体何が起きているのでしょうか?

まず理解すべきこと: db push が成功する条件

エラーを理解する前に、supabase db push正常に動作する条件を明確にしましょう。

db push の正常な動作

$ supabase db push
Applying migration 20240115120000_create_users_table.sql...
Migration applied successfully.

このシンプルな成功メッセージの裏で、何が起きているのでしょうか?

成功のための3つの条件

flowchart TD
    A[supabase db push] --> B{条件1:\nローカルに新しい\nマイグレーションがある?}
    B -->|Yes| C{条件2:\nリモート履歴に\n記録がない?}
    B -->|No| Z[何もしない\nすでに同期済み]
    C -->|Yes| D{条件3:\n実際のスキーマに\n影響しない?}
    C -->|No| E[エラー:\nalready applied]
    D -->|Yes| F[マイグレーション実行]
    D -->|No| G[エラー:\nrelation exists]
    F --> H[履歴テーブルに記録]
    H --> I[成功!]

具体的には:

条件1: ローカルに新規マイグレーションファイルがある

# ローカルにこのファイルがある
supabase/migrations/20240115120000_create_users_table.sql

条件2: リモートの履歴テーブルに未記録

-- リモートで確認すると、このversionが存在しない
SELECT version FROM supabase_migrations.schema_migrations 
WHERE version = '20240115120000';
-- (0 rows)

条件3: SQLの実行が成功する

マイグレーションファイルのSQL文が、現在のスキーマに対して問題なく実行できる状態。

db push の実行フロー

sequenceDiagram
    participant CLI as supabase CLI
    participant Local as ローカルファイル
    participant Remote as リモートDB
    participant History as schema_migrations

    CLI->>Local: マイグレーションファイルを読み込み
    CLI->>History: 適用済み履歴を取得
    CLI->>CLI: 差分を計算
(ローカル - リモート履歴) alt 未適用のマイグレーションあり loop 各マイグレーション CLI->>Remote: BEGIN TRANSACTION CLI->>Remote: SQLを実行 CLI->>History: version, name, statementsを記録 CLI->>Remote: COMMIT end CLI-->>CLI: 成功 else すべて適用済み CLI-->>CLI: 何もしない(Already up to date) end

実際の成功例

ステップ1: 新しいマイグレーションを作成

$ supabase migration new create_users_table
Created new migration at supabase/migrations/20240115120000_create_users_table.sql

ステップ2: SQLを記述

CREATE TABLE public.users (
    id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
    email TEXT UNIQUE NOT NULL,
    created_at TIMESTAMPTZ DEFAULT NOW()
);

ステップ3: db push を実行

$ supabase db push
Applying migration 20240115120000_create_users_table.sql...
Migration applied successfully.

ステップ4: 裏で何が起きたか

-- リモートで実行された処理
BEGIN;
  -- 1. マイグレーションのSQLを実行
  CREATE TABLE public.users (...);
  
  -- 2. 履歴テーブルに記録
  INSERT INTO supabase_migrations.schema_migrations (version, name, statements)
  VALUES ('20240115120000', 'create_users_table', '{"CREATE TABLE ..."}');
COMMIT;

重要な仕組み: トランザクション保証

db push は、各マイグレーションをトランザクション内で実行します。

BEGIN;
  -- マイグレーションのSQL実行
  -- 履歴への記録
COMMIT;  -- すべて成功した場合のみコミット

これにより:

  • 全成功 または 全失敗 が保証される
  • 途中でエラーが起きても、スキーマは変更されない
  • 履歴とスキーマの整合性が保たれる

成功時の状態変化

実行前:
  ローカル: 20240115120000_create_users_table.sql ✓
  リモート履歴: (なし)
  リモートスキーマ: usersテーブルなし

実行後:
  ローカル: 20240115120000_create_users_table.sql ✓
  リモート履歴: 20240115120000 ✓
  リモートスキーマ: usersテーブルあり ✓

この3つの同期状態が、正常な状態です。

エラーの正体: 「状態」の不整合

では、冒頭のエラーはなぜ起きたのでしょうか?

答えは、この3つの同期状態が崩れたときです。

Supabaseのマイグレーションシステムは、2つの情報を照合して動作します。

flowchart LR
    subgraph ローカル
        A[supabase/migrations/\nディレクトリ]
    end
    subgraph リモート
        B[schema_migrations\nテーブル]
        C[実際のスキーマ]
    end
    A -->|比較| B
    B -->|追跡| C
  • ローカル: supabase/migrations/ ディレクトリ内のSQLファイル
  • リモート: supabase_migrations.schema_migrations テーブル(実行履歴)

supabase db push は、この2つを比較して「ローカルにあるがリモートにない」マイグレーションだけを実行します。問題は、この比較がうまくいかない時に起きます。

3つの失敗パターンと原因

パターン1: 「relation already exists」

Error: relation "users" already exists

原因: マイグレーションファイルの内容がすでに適用されているが、履歴テーブルに記録されていない。

よくあるシナリオ:

  • Supabase Studioで直接テーブルを作成した
  • 別の手段(psqlなど)でSQLを実行した
  • db push が途中で失敗し、一部だけ適用された

パターン2: 「already been applied」

Error: migration 20240115120000 has already been applied

原因: 履歴テーブルには記録があるが、同じタイムスタンプのマイグレーションを再度適用しようとしている。

よくあるシナリオ:

  • 適用済みマイグレーションと同じタイムスタンプで新しいファイルを作成した
  • db push を誤って複数回実行した
  • リモートに既に適用済みのマイグレーションをローカルで再作成した

パターン3: 「not in sync」

Error: migration history is not in sync
Remote has migrations not found locally: 20240114090000

原因: リモートには適用済みの履歴があるが、対応するローカルファイルが存在しない。

よくあるシナリオ:

  • チームメンバーが作成したマイグレーションを git pull していない
  • ローカルでマイグレーションファイルを削除してしまった
  • 別ブランチで作成されたマイグレーションがリモートに適用された

状態を確認する方法

トラブルシューティングの第一歩は、現在の状態を正確に把握することです。

リモートの履歴を確認

supabase db remote status

または、直接SQLで確認:

SELECT version, name, statements 
FROM supabase_migrations.schema_migrations 
ORDER BY version;

ローカルのファイルを確認

ls -la supabase/migrations/

差分を可視化

supabase db diff

このコマンドは、現在のリモートスキーマとローカルのマイグレーションファイルを適用した結果の差分を表示します。

各パターンの修正方法

パターン1の修正: スキーマは存在するが履歴がない

履歴テーブルに手動でレコードを追加し、「このマイグレーションは適用済み」とマークします。

INSERT INTO supabase_migrations.schema_migrations (version, name, statements)
VALUES ('20240115120000', 'create_users_table', NULL);

注意: この方法は、スキーマが本当にマイグレーションファイルの内容と一致している場合のみ使用してください。

パターン2の修正: 重複したタイムスタンプ

選択肢A: 新しいタイムスタンプでマイグレーションを作り直す

# 重複したマイグレーションファイルを削除
rm supabase/migrations/20240115120000_duplicate_migration.sql

# 新しいタイムスタンプで作成し直す
supabase migration new create_new_feature

選択肢B: 履歴から該当バージョンを削除する(慎重に)

-- リモートDBに接続して実行(注意: データ整合性に影響する可能性)
DELETE FROM supabase_migrations.schema_migrations 
WHERE version = '20240115120000';

その後、改めて db push を実行。

注意: Supabaseはマイグレーションファイルの内容をチェックサム検証していません。履歴テーブルの version(タイムスタンプ)のみで適用済みかを判断します。そのため、適用済みマイグレーションファイルの内容を変更しても検出されませんが、絶対に変更してはいけません。変更すると、環境間でスキーマの不整合が発生します。

パターン3の修正: ローカルにファイルがない

# チームメンバーの変更を取得
git pull origin main

# または、リモートから差分を取り込む
supabase db pull

db pull は、リモートのスキーマ変更をマイグレーションファイルとして生成します。

実践トラブル事例: Supabase MCPとAIコーディング

事例: AIがマイグレーションを直接実行してしまう

Supabase MCP を使ってCursorClaude Desktop でAIコーディングしていると、思わぬトラブルに遭遇することがあります。

よくある状況:

AIに「usersテーブルを作成して」と指示すると、AIはSupabase MCP経由でリモートデータベースに直接SQLを実行します。

# AIが実行するSQL(MCP経由)
CREATE TABLE public.users (
    id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
    email TEXT UNIQUE NOT NULL,
    created_at TIMESTAMPTZ DEFAULT NOW()
);

テーブルは無事作成されますが、その後 supabase db push しようとすると:

$ supabase db push
Error: migration history is not in sync with local migrations
Local migrations not found on remote:
  20240115120000_create_users_table.sql

あるいは、マイグレーションファイルを後から作成して push すると:

Error: cannot apply migration 20240115120000_create_users_table.sql: 
relation "users" already exists

なぜこの問題が起きるのか

flowchart TD
    A[AIに指示:\nusersテーブル作成] --> B[AI判断:\nMCP経由で直接実行]
    B --> C[リモートDBに\nCREATE TABLE実行]
    C --> D{履歴テーブルに記録?}
    D -->|No| E[スキーマだけ変更\n履歴なし]
    E --> F[後でdb push]
    F --> G[エラー:\nテーブルが既に存在]
    
    style D fill:#ff9999
    style E fill:#ff9999
    style G fill:#ff9999

問題の本質:

  1. AIがMCP経由でSQLを直接実行

    • CREATE TABLE などをリモートDBに即座に実行
    • 履歴テーブル(schema_migrations)には記録されない
  2. ローカルのマイグレーションファイルが存在しない

    • supabase/migrations/ ディレクトリには何も作成されていない
    • Gitで管理される変更履歴がない
  3. 状態の不整合が発生

    ローカル: マイグレーションファイルなし
    リモート履歴: 記録なし
    リモートスキーマ: usersテーブル存在 ✓
    

対処方法1: リモートの変更をマイグレーションファイルに取り込む

最もシンプルな解決策は、db pull でリモートの変更を取り込むことです。

# リモートのスキーマ変更を検出してマイグレーションファイル化
supabase db pull

実行結果:

Pulling schema from remote database...
Created new migration supabase/migrations/20240115135500_remote_schema.sql

生成されたファイル(supabase/migrations/20240115135500_remote_schema.sql)には、リモートとローカルの差分が含まれています:

-- このファイルには、リモートで直接作成された users テーブルの定義が含まれる
CREATE TABLE public.users (
    id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
    email TEXT UNIQUE NOT NULL,
    created_at TIMESTAMPTZ DEFAULT NOW()
);

メリット:

  • リモートの実際の状態を確実にキャプチャできる
  • 他のチームメンバーも同じマイグレーションファイルを共有できる

注意点:

  • AIが作成したスキーマの詳細(インデックス、制約など)が期待通りか確認が必要
  • 生成されたファイル名は自動的なタイムスタンプなので、わかりやすい名前に変更することを推奨

対処方法2: リモートの変更を履歴として記録する

すでにマイグレーションファイルを作成済みで、リモートのスキーマと一致している場合は、履歴テーブルに手動で記録します。

-- リモートDBに接続して実行
INSERT INTO supabase_migrations.schema_migrations (version, name, statements)
VALUES ('20240115120000', 'create_users_table', NULL);

その後、db push を実行:

$ supabase db push
Already up to date.

この方法を使うべき条件:

  • ローカルのマイグレーションファイルが既に存在する
  • リモートのスキーマとマイグレーションファイルの内容が完全に一致している
  • AIが実行したSQLの内容を正確に把握している

対処方法3: リモートをクリーンアップして再適用(開発環境のみ)

開発初期段階で、リモートのスキーマをリセットできる場合:

# 1. リモートDBのスキーマを削除(注意: データも失われる)
supabase db reset --linked

# 2. ローカルのマイグレーションを適用
supabase db push

警告:

  • この方法は本番環境では絶対に使用しないこと
  • 既存のデータがすべて失われる
  • 開発の初期段階でのみ有効

予防策: AIに正しい指示を出す

Supabase MCPを使う際は、AIに明示的に「マイグレーションファイルを作成する」よう指示します。

悪い指示例:

usersテーブルを作成して

→ AIがMCP経由で直接SQLを実行する可能性が高い

良い指示例:

usersテーブルのマイグレーションファイルを作成して。
supabase migration new を使って、ファイルにCREATE TABLE文を記述してください。
リモートには push しないで。

さらに良い指示例:

以下の手順でusersテーブルを追加:
1. supabase migration new create_users_table を実行
2. 生成されたファイルにCREATE TABLE文を記述
3. ローカルで supabase db reset してテスト
4. 確認後、supabase db push で本番適用

MCPでリモートDBに直接SQLを実行しないでください。

ベストプラクティス: AIとの協調作業

flowchart LR
    A[AIに指示] --> B{指示内容}
    B -->|推奨| C[マイグレーションファイル作成]
    B -->|避ける| D[直接SQL実行]
    C --> E[supabase migration new]
    E --> F[ファイル編集]
    F --> G[ローカルテスト]
    G --> H[db push]
    D --> I[履歴と不整合]
    
    style C fill:#99ff99
    style D fill:#ff9999
    style I fill:#ff9999

推奨ワークフロー:

  1. AIにマイグレーション生成を依頼

    「create_posts_table というマイグレーションファイルを作成して、
    postsテーブルの定義を含めてください」
    
  2. 生成されたファイルをレビュー

    • SQLの内容が意図通りか確認
    • セキュリティ(RLS)設定が含まれているか確認
  3. ローカルでテスト

    supabase db reset
    
  4. 問題なければコミット

    git add supabase/migrations/
    git commit -m "Add posts table migration"
    
  5. リモートに適用

    supabase db push
    

AIアシスタントとマイグレーション

トラブル事例4: ローカルのマイグレーションがリモート履歴の途中に挿入される

チーム開発やブランチ作業で発生しやすいパターンです。

$ supabase db push
Found local migration files to be inserted before the last migration on remote database.

Rerun the command with --include-all flag to apply these migrations:
supabase/migrations/20251223100000_add_spec_version_to_mock_applications.sql

なぜこれが起きるのか:

flowchart LR
    subgraph リモート履歴
        R1[20251220_feature_a] --> R2[20251225_feature_b]
    end
    subgraph ローカル
        L1[20251220_feature_a] --> L2[20251223_new_column] --> L3[20251225_feature_b]
    end
    L2 -->|挿入位置| R1
    
    style L2 fill:#ffcc00

リモートでは 2025122020251225 の順で適用済みですが、ローカルには 20251223 のマイグレーションが存在します。これは以下のような状況で発生します:

  • ブランチ作業: 別ブランチで作成したマイグレーションをマージした
  • チーム開発: 他のメンバーが先に db push して、自分のマイグレーションが「間に挟まる」形になった
  • 作業順序の逆転: 古いタイムスタンプのマイグレーションを後から追加した

対処方法1: --include-all フラグを使用(推奨)

supabase db push --include-all

このフラグを付けると、タイムスタンプの順序に関わらず、未適用のマイグレーションをすべて適用します。

注意点:

  • マイグレーション間に依存関係がある場合は問題が発生する可能性がある
  • 実行前に supabase db diff で差分を確認することを推奨

対処方法2: タイムスタンプを更新

マイグレーションがまだ他の環境に適用されていない場合は、タイムスタンプを最新に更新できます:

# 現在時刻でタイムスタンプを生成
TIMESTAMP=$(date +%Y%m%d%H%M%S)

# ファイル名を変更
mv supabase/migrations/20251223100000_add_spec_version.sql \
   supabase/migrations/${TIMESTAMP}_add_spec_version.sql

予防策:

  • チームで作業する場合は、git pullsupabase db pull を頻繁に実行
  • マイグレーション作成時は必ず supabase migration new コマンドを使用(現在時刻が自動設定される)
  • ブランチをマージする前に、マイグレーションのタイムスタンプを確認

トラブル事例5: AIが古いタイムスタンプを生成してしまう

AIコーディング中、稀にAIがマイグレーションファイルを手動作成する際、極端に古いタイムスタンプを付けてしまうことがあります。

問題のあるファイル例:

supabase/migrations/20200101000000_add_new_feature.sql

このファイルは supabase db push 時に以下の問題を引き起こします:

$ supabase db push
Error: migration 20200101000000 comes before the latest applied migration 20240115120000

なぜこれが問題なのか:

flowchart LR
    A[既存マイグレーション
20240115120000] --> B[AIが作成
20200101000000] B --> C[タイムスタンプ順では
Aより前] C --> D[実行順序が逆転] D --> E[依存関係エラー] style B fill:#ff9999 style D fill:#ff9999 style E fill:#ff9999

マイグレーションはタイムスタンプ順に実行されるため、新しい機能を追加するマイグレーションが既存のマイグレーションより前に実行されようとします。これは:

  • 依存するテーブルがまだ存在しない
  • 実行順序が意図と逆になる
  • 履歴の整合性が崩れる

原因:

AIが supabase migration new コマンドを使わずに、ファイルを直接作成してしまった場合に発生します。

# AIが誤って実行する例
touch supabase/migrations/20200101000000_add_new_feature.sql

対処方法1: ファイル名を修正

# 1. 現在時刻でタイムスタンプを生成
TIMESTAMP=$(date +%Y%m%d%H%M%S)

# 2. ファイル名を変更
mv supabase/migrations/20200101000000_add_new_feature.sql \
   supabase/migrations/${TIMESTAMP}_add_new_feature.sql

# 例: 20200101000000_add_new_feature.sql 
#  → 20240116153045_add_new_feature.sql

対処方法2: 正しいコマンドで作り直す

# 1. 誤ったファイルの内容を一時保存
cp supabase/migrations/20200101000000_add_new_feature.sql /tmp/migration_content.sql

# 2. 誤ったファイルを削除
rm supabase/migrations/20200101000000_add_new_feature.sql

# 3. 正しいコマンドで作成(自動的に正しいタイムスタンプが付く)
supabase migration new add_new_feature

# 4. 内容を復元
cat /tmp/migration_content.sql > supabase/migrations/*_add_new_feature.sql

対処方法3: 既存履歴をリセット(開発初期のみ)

開発の初期段階で、まだリモートに適用していない場合:

# ローカルDBをリセット
supabase db reset

# マイグレーションファイルを全て削除
rm -rf supabase/migrations/*

# 現在のスキーマから新しいマイグレーションを生成
supabase db diff -f initial_schema

予防策: AIに正しいコマンドを使わせる

マイグレーションファイルを作成する際は、必ず以下のコマンドを使ってください:

supabase migration new <マイグレーション名>

ファイルを手動で作成したり、touchコマンドを使ったりしないでください。
タイムスタンプは自動生成されます。

タイムスタンプの重要性:

正しい順序:
20240115120000_create_users.sql      ← 先に実行
20240115130000_create_posts.sql      ← 後で実行(users に依存)
20240116153045_add_new_feature.sql   ← 最後に実行

間違った順序:
20200101000000_add_new_feature.sql   ← 最初に実行されようとする(エラー)
20240115120000_create_users.sql
20240115130000_create_posts.sql

まとめ: MCP使用時の注意点

項目推奨避けるべき
スキーマ変更方法マイグレーションファイル経由MCP経由で直接SQL実行
AIへの指示「migration new で作成」と明示曖昧な指示
ファイル作成方法supabase migration new コマンド手動ファイル作成・touch コマンド
タイムスタンプ自動生成されたものを使用手動で設定・古い日付
順序の問題--include-all で対処依存関係を無視して適用
テスト方法ローカルで db resetリモートで直接確認
適用タイミングレビュー後に db pushAIの実行直後

Supabase MCPは強力なツールですが、マイグレーション管理の原則を理解した上で使用することが重要です。

なぜこの設計なのか: マイグレーションの本質

ここまで見てきたトラブルは、マイグレーションシステムの設計思想を理解すると腑に落ちます。

「宣言的」ではなく「命令的」

Supabaseのマイグレーションは、最終状態を宣言するのではなく、変更の手順を記録する方式です。

宣言的: 「usersテーブルにはemail列があるべき」
命令的: 「ALTER TABLE users ADD COLUMN email TEXT を実行せよ」

命令的アプローチのメリット:

  • 実行順序が明確
  • 複雑な変更(データ移行など)を表現できる
  • 何が起きたか履歴として残る

デメリット:

  • 一度適用したマイグレーションは変更できない
  • 履歴とファイルの整合性を保つ必要がある

タイムスタンプによる順序保証

20240115120000_create_users_table.sql  ← 先に実行
20240115130000_add_email_column.sql    ← 後で実行

ファイル名のタイムスタンプは、単なる命名規則ではありません。実行順序を決定する重要な要素です。これにより:

  • 依存関係のある変更が正しい順序で適用される
  • チームメンバーが同時に作成しても衝突しにくい
  • 履歴が時系列で追跡できる

冪等性の欠如

多くのマイグレーションは冪等(何度実行しても同じ結果)ではありません。

CREATE TABLE users (...);  -- 2回実行するとエラー

だからこそ、履歴テーブルで「何を実行済みか」を厳密に管理する必要があるのです。

トラブルを防ぐワークフロー

理解が深まったところで、トラブルを未然に防ぐワークフローを紹介します。

原則: 「履歴を壊さない」

flowchart TD
    A[スキーマ変更が必要] --> B{変更方法}
    B -->|正しい| C[migration newで\nファイル作成]
    B -->|危険| D[Studioで直接変更]
    B -->|危険| E[psqlで直接変更]
    C --> F[ローカルでテスト]
    F --> G[db pushで適用]
    D --> H[履歴と不整合]
    E --> H

推奨ワークフロー

1. マイグレーションファイルを作成

supabase migration new create_posts_table

2. SQLを記述

-- supabase/migrations/20240116090000_create_posts_table.sql
CREATE TABLE public.posts (
    id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
    user_id UUID REFERENCES public.users(id),
    title TEXT NOT NULL,
    content TEXT,
    created_at TIMESTAMPTZ DEFAULT NOW()
);

ALTER TABLE public.posts ENABLE ROW LEVEL SECURITY;

3. ローカルでテスト

supabase db reset  # ローカルDBを初期化して全マイグレーションを再実行

4. コードレビューとマージ

git add supabase/migrations/
git commit -m "Add posts table migration"
git push

5. リモートに適用

supabase db push

やってはいけないこと

行為理由
適用済みマイグレーションを編集環境間でスキーマが不整合になる(検出されない)
Studioで直接スキーマ変更履歴に記録されない
マイグレーションファイルを削除リモートと不整合になる
タイムスタンプを手動で変更実行順序が狂う可能性

CI/CDでの自動化

マイグレーションの適用をCI/CDパイプラインに組み込むことで、ヒューマンエラーを防げます。

# .github/workflows/deploy.yml
name: Deploy Migrations

on:
  push:
    branches: [main]
    paths:
      - 'supabase/migrations/**'

jobs:
  migrate:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4
      
      - uses: supabase/setup-cli@v1
        with:
          version: latest
      
      - name: Link project
        run: supabase link --project-ref ${{ secrets.SUPABASE_PROJECT_ID }}
        env:
          SUPABASE_ACCESS_TOKEN: ${{ secrets.SUPABASE_ACCESS_TOKEN }}
      
      - name: Push migrations
        run: supabase db push

まとめ: エラーは理解のチャンス

supabase db push の失敗は、マイグレーションシステムが「状態の不整合を検知した」というシグナルです。

重要なポイント:

  • マイグレーションは「変更の履歴」: ファイルと履歴テーブルの整合性が命
  • 一度適用したら変更しない: 追加の変更は新しいマイグレーションで
  • 直接変更は避ける: 必ずマイグレーションファイル経由で変更
  • 状態確認が第一歩: db remote statusdb diff で現状把握

エラーに遭遇したら、まず「ローカルとリモートの状態がどう違うのか」を確認してください。原因がわかれば、適切な対処法が見えてきます。

参考リンク