W

Laravelのマイグレーションをやり直す方法|rollback・refresh・freshの違い

#Laravel #マイグレーション #データベース #artisan

マイグレーションでテーブルを作ったあとに「カラム名を間違えた」「型が違った」と気づくことがあります。

やり直したいのですが、調べると migrate:rollbackmigrate:refreshmigrate:freshmigrate:reset と似たコマンドが並んでいて、どれを使えばいいのか分かりません。しかも選び方を間違えるとデータが全部消えます

この記事では、それぞれの違いと安全な使い分けを解説します。

⚠️ 最初に警告

この記事で紹介するコマンドの多くは、データベースの中身を削除します

  • 本番環境(公開中のサーバー)では絶対に実行しないでください。ユーザーのデータが消えます。
  • 練習用・開発用のデータベースであることを必ず確認してから実行してください。

以下は「自分のパソコンで開発中」を前提に説明します。

4つのコマンドの違い

先に一覧で示します。

コマンド何をするか影響の範囲
migrate:rollback直前のバッチを取り消す(複数ファイルを含むことがある)そのバッチの down() が実行される
migrate:resetすべてのマイグレーションを取り消す全マイグレーションの down() が実行される
migrate:refreshすべて取り消して、もう一度実行同上 + 作り直し
migrate:freshデータベースのテーブルを全削除して、もう一度実行down() を使わず、テーブルを直接削除

ここで大事なのは、「取り消す(down() を実行する)」と「テーブルを削除する」がまったく別の動作だ、という点です。順に説明します。

down() とは: マイグレーションファイルに書く「取り消し用の処理」です。up() が「テーブルを作る」なら、down() は「テーブルを消す」を書きます。取り消しの内容は、この down() に書かれたことがそのまま実行されます

その前に: いまの状態を確認する

やり直す前に、いま何が実行済みなのかを見ておきましょう。

php artisan migrate:status

次のように表示されます。

  Migration name ................................ Batch / Status
  0001_01_01_000000_create_users_table ................ [1] Ran
  0001_01_01_000001_create_cache_table ................ [1] Ran
  0001_01_01_000002_create_jobs_table ................. [1] Ran
  2026_06_17_042743_create_posts_table ................ [2] Ran

注目してほしいのが [1][2] という数字です。これは「バッチ番号」といい、同じタイミングで実行されたマイグレーションのグループを表します。

上の例では、最初の3つが1回目(バッチ1)、posts テーブルが2回目(バッチ2)に実行された、という意味です。この考え方が次の rollback の理解に必要です。

1. migrate:rollback — 直前のバッチを取り消す

開発中にもっともよく使うコマンドです。全体を作り直す freshrefresh に比べれば影響範囲を限定できますが、「安全なコマンド」ではありません。理由は以下で説明します。

php artisan migrate:rollback

取り消されるのは直前のバッチ(いちばん大きい番号のグループ)です。公式ドキュメントにも「直前の “バッチ” を取り消す。複数のマイグレーションファイルを含むことがある」と書かれています。

つまり、「直前の1ファイルだけ」ではありません。もし前回 php artisan migrate を実行したときに3つのファイルがまとめて実行されていたら、その3つすべてが取り消されます。

さらに注意すべき点があります。取り消しで何が起きるかは、マイグレーションファイルの down() に書かれた内容次第です。

  • テーブルを作るマイグレーションなら → そのテーブルが削除される
  • カラムを追加するマイグレーションなら → そのカラム(と中のデータ)が削除される
  • インデックスの変更や独自の SQL が書かれていれば → それが実行される

「テーブル1つが消えるだけ」とは限らないので、実行前に必ず対象ファイルの down() を読んでください。次に紹介する --pretend を使えば、実際に何が起きるかを事前に確認できます。

取り消す量を指定する

「1つだけ戻したい」というときは --step を使います。

php artisan migrate:rollback --step=1

--stepマイグレーションファイルの個数を指定します。バッチ単位ではないので、細かく戻したいときに便利です。

実行前に中身を確認する(おすすめ)

--pretend(プリテンド=ふりをする)を付けると、実際には実行せず、どんな SQL が走るかだけを表示します。

php artisan migrate:rollback --pretend

次のように、実行される内容が確認できます。

 INFO  Rolling back migrations.

  2026_06_17_042743_create_posts_table
  ⇂ drop table if exists "posts"

「本当にこれを消していいのか」を事前に確かめられるので、不安なときは必ず付けてください。

典型的な使い方

カラム名を間違えたときの直し方は、次の3ステップです。

# 1. 直前のマイグレーションを取り消す
php artisan migrate:rollback

# 2. マイグレーションファイルを修正する(エディタで編集)

# 3. もう一度実行する
php artisan migrate

これが基本の流れです。

2. migrate:reset — すべてのマイグレーションを取り消す

公式の説明は「すべてのマイグレーションをロールバックする」です。作り直しはしません

php artisan migrate:reset

rollback を最初のバッチまで繰り返すイメージです。ここでも実行されるのは各マイグレーションの down() なので、「データベースが完全にまっさらになる」わけではありません

  • マイグレーションで作っていないテーブル(手動で作ったものなど)は残ります
  • down() にテーブル削除が書かれていなければ、そのテーブルも残ります

そのあと php artisan migrate を実行すれば作り直せますが、それなら次の refresh を使う方が早いです。

3. migrate:refresh — 全部取り消して、もう一度実行

php artisan migrate:refresh

公式の説明は「Reset and re-run all migrations(すべて取り消して、再実行する)」です。つまり resetmigrate を続けて実行するのと同じです。

各マイグレーションの「取り消す処理」(down() メソッド)が順に呼ばれるため、down() が正しく書かれていないと失敗します

4. migrate:fresh — テーブルを全削除して、もう一度実行

php artisan migrate:fresh

公式の説明は「Drop all tables and re-run all migrations(すべてのテーブルを削除して、再実行する)」です。

refresh との決定的な違い

ここが最重要ポイントです。

  • refresh: 各マイグレーションの down() を呼んで、順番に取り消す
  • fresh: down() を使わず、データベース内のテーブルを直接削除する

freshdown() に依存しないので、down() が正しく書かれていない状態でもリセットできるのが利点です。開発中に「もうぐちゃぐちゃだから作り直したい」というときに使います。

ただしその分、強力で危険です。次の2点に注意してください。

⚠️ 注意1: 同じデータベースを他のアプリと共有している場合は使わない

公式ドキュメントには、次のように明記されています。

migrate:fresh コマンドは、接頭辞(プレフィックス)に関係なくすべてのテーブルを削除します。他のアプリケーションと共有しているデータベースで開発している場合、このコマンドの使用には注意が必要です。

つまり fresh は「このアプリのテーブル」だけを選んで消すわけではありません。そのデータベースにあるテーブルを全部消します。レンタルサーバーなどで1つのデータベースを複数のアプリで共有している場合、他のアプリのデータまで消えます

心当たりがある場合は fresh を使わず、refreshrollback を使ってください。

⚠️ 注意2: 「必ず成功する」わけではない

down() に依存しないとはいえ、データベースの権限が足りない、外部キー制約が絡んでいる、といった理由で失敗することはあります。エラーが出たらメッセージを読んで対処してください。

なお、fresh が対象にするのは既定のデータベース接続です。別の接続を指定したい場合は --database オプションを使います。

テストデータも一緒に入れる

やり直したあと、テストデータ(シーダー)も入れ直したいことがよくあります。--seed を付ければ1コマンドで済みます。

php artisan migrate:fresh --seed

migrate:refresh --seed も同様に使えます。開発中はこの形をよく使います。

どれを使えばいいか

迷ったときの判断です。

状況使うコマンド
さっき作ったテーブルを直したいmigrate:rollback → 修正 → migrate
開発中で、全部リセットしたいmigrate:fresh --seed
down() の動作も確認したいmigrate:refresh
本番環境どれも使わない(後述)

開発中の実用としては、rollbackfresh --seed の2つを覚えておけば十分です。

本番環境ではどうするか

本番のデータベースには、実際のユーザーのデータが入っています。

本番では rollbackresetrefreshfresh のいずれも原則として使わないでください。freshrefresh はもちろん、rollbackdown() の内容次第でカラムごとデータを消します。取り返しがつきません。

そのため Laravel は、本番環境(APP_ENV=production)でこれらを実行しようとすると確認を求めて止まります--force を付ければ無視して実行できてしまうので、意味を分からずに付けないでください。

どうしても本番で構造を戻す必要がある場合は、最低限これらを守ってください。

  • 事前にデータベースのバックアップを取る
  • 実行内容を --pretend で確認し、他の人にレビューしてもらう
  • メンテナンス時間を設けてから実施する

本番でテーブル構造を変えたいときは、**取り消すのではなく「変更するための新しいマイグレーションを追加する」**のが正しいやり方です。

# 例: カラムを追加するマイグレーションを新規作成する
php artisan make:migration add_status_to_posts_table --table=posts

「前に進んで直す」と覚えてください。

まとめ

  • まず migrate:status で現在の状態とバッチ番号を確認する。
  • migrate:rollback が戻すのは「直前のバッチ」。1ファイルとは限らず、複数まとめて戻ることがある(1つだけなら --step=1)。
  • 何が起きるかはマイグレーションの down() 次第。実行前に --pretend で確認する習慣をつける。
  • 開発中に全部やり直すなら migrate:fresh --seed が手軽。
  • refreshdown() を実行する / fresh はテーブルを直接削除する。これが両者の決定的な違い。
  • fresh は接頭辞に関係なく全テーブルを消す。データベースを他のアプリと共有しているなら使わない。
  • 本番環境では rollbackresetrefreshfresh を原則使わない。変更用のマイグレーションを新しく作って前に進める。

マイグレーションの書き方そのものは、カリキュラムの マイグレーションでテーブルを作る、テストデータの作り方は シーダーとファクトリでテストデータを作る で解説しています。