Question
Is there an easy way to run one specific Laravel migration file without migrating the database to a particular version? I want to execute a single migration only.
Short Answer
You will learn how Laravel migration files are discovered and recorded, how to target a migration path with Artisan, and why running one migration can be unsafe when it depends on earlier schema changes.
Concept
Laravel migrations are version-controlled PHP classes that change a database schema. They can create tables, add columns, create indexes, or modify data.
Normally, Laravel runs all pending migrations in timestamp order:
php artisan migrate
Laravel stores completed migration names in the migrations database table. Before running a migration, it checks that table. If the file has already been recorded, Laravel does not run it again.
To target a particular file, use Artisan's --path option:
php artisan migrate --path=database/migrations/2024_01_15_120000_add_status_to_orders_table.php
This asks Laravel to look at that path rather than its usual migration directory. It still uses the migration history table, so the targeted migration must be pending.
Running a file individually is useful for focused development or recovery work, but migrations are usually intended to run in order. A migration that adds a column cannot succeed if the table was supposed to be created by an earlier migration that has not run.
Mental Model
Think of migrations as numbered construction instructions for a building.
- A normal migration run follows every unfinished instruction in order.
--pathis like taking one instruction from the folder and trying to perform only that task.- Laravel's
migrationstable is the completion checklist. Once an instruction is checked off, Laravel will not repeat it automatically.
You can install a door by itself only if the wall and doorway already exist. Similarly, a single migration works only when its required tables, columns, and data already exist.
Syntax and Examples
Use php artisan migrate with --path to point to a migration file or directory. The path is normally relative to the Laravel project root.
php artisan migrate --path=database/migrations/2024_05_10_090000_create_audit_logs_table.php
Example migration:
<?php
use Illuminate\Database\Migrations\Migration;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Support\Facades\Schema;
return new class extends Migration
{
public function up(): void
{
Schema::create('audit_logs', function (Blueprint $table) {
$table->id();
$table->string('event');
$table->timestamps();
});
}
public function down(): void
{
Schema::dropIfExists('audit_logs');
}
};
If this migration is pending, the command runs its up() method and records its filename in the migrations table.
You can also target a directory, which runs the pending migrations in that directory:
php artisan migrate --path=database/migrations/reporting
In production, include --force because Laravel otherwise asks for confirmation:
php artisan migrate --force --path=database/migrations/2024_05_10_090000_create_audit_logs_table.php
Use --force carefully: it bypasses the production confirmation prompt; it does not make the migration safer.
Step by Step Execution
Suppose the database already has an orders table, and this pending migration adds a status column:
return new class extends Migration
{
public function up(): void
{
Schema::table('orders', function (Blueprint $table) {
$table->string('status')->default('pending');
});
}
public function down(): void
{
Schema::table('orders', function (Blueprint $table) {
$table->dropColumn('status');
});
}
};
Run it with:
php artisan migrate --path=database/migrations/2024_06_01_100000_add_status_to_orders_table.php
What happens:
- Artisan starts Laravel and connects using the configured database connection.
- Laravel loads the specified migration path.
- It checks the
migrationstable to see whether2024_06_01_100000_add_status_to_orders_tablehas already run. - If it is pending, Laravel calls
up(). Schema::table()sends SQL to add thestatuscolumn toorders.- Laravel adds the migration name and a batch number to the
migrationstable. - Later, a rollback can call
down()for the relevant migration batch.
If orders does not exist, step 5 fails. This is why checking dependencies is essential before targeting one migration.
Real World Use Cases
- Developing a feature: Run a new migration that adds fields for a feature while testing locally.
- Modular application code: Keep package or module migrations in a separate directory and run that directory during setup.
- Focused troubleshooting: Apply a known pending migration in a disposable local or staging database to reproduce a schema problem.
- Deployment verification: Confirm that a specific migration is present and works in staging before a broader release.
- Package installation: A Laravel package may publish migrations into a known path that an application runs during installation.
For a normal deployment, prefer the complete pending sequence:
php artisan migrate --force
That preserves the intended order of schema changes.
Real Codebase Usage
In production codebases, migrations are treated as an ordered, append-only history of the database.
Common practices include:
- Run all pending migrations in CI/CD. Deployment pipelines usually execute
php artisan migrate --force, not individual files. - Use guard-style checks only when justified.
Schema::hasTable()orSchema::hasColumn()can help with legacy databases, but should not hide a broken migration history. - Make
down()meaningful when possible. A reversible migration helps during development and controlled rollbacks. - Avoid editing migrations that have been shared. Create a new migration to correct an earlier change. Other environments may already have recorded the original file.
- Use transactions where the database supports them. Laravel migrations can often be rolled back automatically after a failure, but support depends on the database engine and the SQL operation.
- Test schema changes against realistic data. A new non-null column, unique index, or foreign key may fail because existing rows do not meet its rules.
A migration should assume all prior required migrations have already executed. If that assumption is not true, fix the environment's migration history rather than repeatedly bypassing the sequence.
Common Mistakes
Using migrate:rollback to undo one arbitrary file
php artisan migrate:rollback
This rolls back the last batch, not a migration selected by filename. A batch may contain several migrations.
Avoid it: inspect the migration status and understand the batch before rolling back:
php artisan migrate:status
Expecting a completed migration to run again
php artisan migrate --path=database/migrations/2024_05_10_090000_create_audit_logs_table.php
If Laravel already recorded this migration, the command skips it. Deleting the migration row manually can cause duplicate-table or duplicate-column errors.
Avoid it: write a new migration for a new schema change. In a disposable local database, you can reset or rebuild the database intentionally.
Running a dependent migration before its prerequisites
Schema::table('orders', function (Blueprint $table) {
$table->string('status');
});
This fails if the orders table has not been created.
Avoid it: run the earlier migrations first, or use a clean database and run the normal migration sequence.
Using an incorrect path
php artisan migrate --path=/database/migrations/file.php
A leading slash commonly means an absolute filesystem path, not a path inside the project.
Avoid it: start with a project-relative path:
php artisan migrate --path=database/migrations/file.php
Editing an old migration after it has run elsewhere
Changing a previously applied migration does not make Laravel execute it again in environments where it is already recorded.
Avoid it: add a new migration that makes the next required change.
Comparisons
| Task | Command or approach | Important behavior |
|---|---|---|
| Run every pending migration | php artisan migrate | Uses normal migration directories and timestamp order. |
| Run migrations from one path | php artisan migrate --path=database/migrations/reporting | Runs pending migrations found in that directory. |
| Target one migration file | php artisan migrate --path=database/migrations/file.php | Runs it only if it is pending and its dependencies exist. |
| See migration state | php artisan migrate:status | Shows which migrations have run and their batches. |
| Undo recent work | php artisan migrate:rollback | Rolls back the latest batch, not an arbitrary file. |
| Rebuild a disposable database | php artisan migrate:fresh | Drops tables, then runs migrations; destructive. |
--path controls where Laravel looks for migration files. It does not ignore the migration history table, force a completed migration to rerun, or resolve missing dependencies.
Cheat Sheet
# Run all pending migrations
php artisan migrate
# Check which migrations have run
php artisan migrate:status
# Run one pending migration file
php artisan migrate --path=database/migrations/2024_05_10_090000_create_audit_logs_table.php
# Run pending migrations in a directory
php artisan migrate --path=database/migrations/reporting
# Production usage: bypass the confirmation prompt
php artisan migrate --force --path=database/migrations/2024_05_10_090000_create_audit_logs_table.php
# Roll back the latest migration batch
php artisan migrate:rollback
Rules to remember:
- Migration filenames are ordered by timestamp.
- Laravel records completed migrations in the
migrationstable. - A recorded migration is skipped, even when its path is specified.
- A single migration must have all required schema dependencies already available.
- Prefer a new migration over editing or rerunning an old shared migration.
- Do not use
migrate:freshon a database containing data you need.
FAQ
Can I run a single Laravel migration by filename?
Yes. Point migrate at its file with --path:
php artisan migrate --path=database/migrations/your_migration.php
It runs only when Laravel considers that migration pending.
Why does Laravel skip my migration?
Laravel has likely already recorded it in the migrations table. Check with php artisan migrate:status.
Does --path run a migration regardless of its dependencies?
No. It only selects the file or directory to scan. The migration still needs the required tables, columns, and data to exist.
Can I rerun a migration after changing its code?
Not automatically if it has already run. The safe approach is to create a new migration containing the additional change. For local development, rebuild or roll back only when you understand the impact.
Does migrate:rollback undo one selected migration?
Usually no. It rolls back the most recently executed migration batch. That batch can include multiple migration files.
Should I run one migration directly in production?
Only when you have verified the exact file, its dependencies, backups, and deployment plan. Most production deployments should run all pending migrations in their intended order.
Should I include --force?
Use --force in a non-interactive production deployment when you deliberately want to bypass Laravel's confirmation prompt. It does not bypass migration tracking or database errors.
Mini Project
Description
Create a migration that adds a priority column to an existing tasks table, then run that migration by its file path. This mirrors a common feature update: an application already has task records and now needs a way to classify their urgency.
Goal
Add a safe default priority to existing and future tasks, then apply only the new migration locally.
Requirements
:[
Keep learning
Related questions
Add a Default Value to an Existing Column in a Rails Migration
Learn how to add or change a default value on an existing database column using Rails Active Record migrations safely.
Calling a Class Method from an Instance in Ruby
Learn how to call a class method from an instance in Ruby using self.class, with examples, pitfalls, and practical usage patterns.
Calling an Overridden Monkey-Patched Method in Ruby
Learn how to call the original method when monkey patching in Ruby, including alias_method patterns, examples, pitfalls, and practical usage.