Laravelのマイグレーションをやり直す方法|rollback・refresh・freshの違い
マイグレーションでテーブルを作ったあとに「カラム名を間違えた」「型が違った」と気づくことがあります。
やり直したいのですが、調べると migrate:rollback、migrate:refresh、migrate:fresh、migrate: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 — 直前のバッチを取り消す
開発中にもっともよく使うコマンドです。全体を作り直す fresh や refresh に比べれば影響範囲を限定できますが、「安全なコマンド」ではありません。理由は以下で説明します。
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(すべて取り消して、再実行する)」です。つまり reset と migrate を続けて実行するのと同じです。
各マイグレーションの「取り消す処理」(down() メソッド)が順に呼ばれるため、down() が正しく書かれていないと失敗します。
4. migrate:fresh — テーブルを全削除して、もう一度実行
php artisan migrate:fresh
公式の説明は「Drop all tables and re-run all migrations(すべてのテーブルを削除して、再実行する)」です。
refresh との決定的な違い
ここが最重要ポイントです。
refresh: 各マイグレーションのdown()を呼んで、順番に取り消すfresh:down()を使わず、データベース内のテーブルを直接削除する
fresh は down() に依存しないので、down() が正しく書かれていない状態でもリセットできるのが利点です。開発中に「もうぐちゃぐちゃだから作り直したい」というときに使います。
ただしその分、強力で危険です。次の2点に注意してください。
⚠️ 注意1: 同じデータベースを他のアプリと共有している場合は使わない
公式ドキュメントには、次のように明記されています。
migrate:freshコマンドは、接頭辞(プレフィックス)に関係なくすべてのテーブルを削除します。他のアプリケーションと共有しているデータベースで開発している場合、このコマンドの使用には注意が必要です。
つまり fresh は「このアプリのテーブル」だけを選んで消すわけではありません。そのデータベースにあるテーブルを全部消します。レンタルサーバーなどで1つのデータベースを複数のアプリで共有している場合、他のアプリのデータまで消えます。
心当たりがある場合は fresh を使わず、refresh か rollback を使ってください。
⚠️ 注意2: 「必ず成功する」わけではない
down() に依存しないとはいえ、データベースの権限が足りない、外部キー制約が絡んでいる、といった理由で失敗することはあります。エラーが出たらメッセージを読んで対処してください。
なお、fresh が対象にするのは既定のデータベース接続です。別の接続を指定したい場合は --database オプションを使います。
テストデータも一緒に入れる
やり直したあと、テストデータ(シーダー)も入れ直したいことがよくあります。--seed を付ければ1コマンドで済みます。
php artisan migrate:fresh --seed
migrate:refresh --seed も同様に使えます。開発中はこの形をよく使います。
どれを使えばいいか
迷ったときの判断です。
| 状況 | 使うコマンド |
|---|---|
| さっき作ったテーブルを直したい | migrate:rollback → 修正 → migrate |
| 開発中で、全部リセットしたい | migrate:fresh --seed |
down() の動作も確認したい | migrate:refresh |
| 本番環境 | どれも使わない(後述) |
開発中の実用としては、rollback と fresh --seed の2つを覚えておけば十分です。
本番環境ではどうするか
本番のデータベースには、実際のユーザーのデータが入っています。
本番では rollback・reset・refresh・fresh のいずれも原則として使わないでください。fresh や refresh はもちろん、rollback も down() の内容次第でカラムごとデータを消します。取り返しがつきません。
そのため 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が手軽。 refreshはdown()を実行する /freshはテーブルを直接削除する。これが両者の決定的な違い。freshは接頭辞に関係なく全テーブルを消す。データベースを他のアプリと共有しているなら使わない。- 本番環境では
rollback・reset・refresh・freshを原則使わない。変更用のマイグレーションを新しく作って前に進める。
マイグレーションの書き方そのものは、カリキュラムの マイグレーションでテーブルを作る、テストデータの作り方は シーダーとファクトリでテストデータを作る で解説しています。