Mark migrations as run
$ grim migrate:mark-applied --all-existing --dry-run --remote
A train may rename a migration file: same table, new date in the name. An instance that took every train never notices. An instance that skipped a few meets the renamed file as a migration it has not run, tries to create a table it already has, and migrate stops with Base table or view already exists. Laravel has no command for the fix, which is a row in the migrations table and nothing else. This is that command.
It never runs a migration. It writes the rows that say one ran, inside the app, with the app's own database configuration, and then a normal migrate carries on with the rest.
Usage
$ grim migrate:mark-applied --all-existing --dry-run # local container: what would be marked
$ grim migrate:mark-applied --all-existing # mark them
$ grim migrate:mark-applied 2026_05_03_000002_create_orders_table # one by name
$ grim migrate:mark-applied --all-existing --dry-run --remote # the deployed app, default environment
$ grim migrate:mark-applied --all-existing --remote=stagingWithout --remote it talks to the app container of the project in the current directory. With it, to the deployed app, found the way grim remote:artisan finds it: ~/.grim/servers.json on this machine.
Arguments and options
Record migrations as run without running them, for tables that already exist under a renamed migration
Usage
grim migrate:mark-applied [--all-existing] [--dry-run] [--remote [REMOTE]] [--] [<migrations>...]Arguments
| Argument | Description |
|---|---|
migrations |
Migration names to mark, with or without .php (optional, repeatable) |
Options
| Option | Description |
|---|---|
--all-existing |
Mark every pending migration whose Schema::create tables already exist |
--dry-run |
Print what would be marked and write nothing |
--remote[=REMOTE] |
Run inside the deployed app instead of the local container; takes the environment name, the project default without one |
What it actually does
- Builds a script that lists the migration files the app knows — the default directory and every path a module registered — and the names the
migrationstable already holds. - Picks what to mark. A name you gave is marked when it is pending; one already recorded is skipped, one the app has no file for is an error. With
--all-existingevery pending migration is read, and the ones whoseSchema::createtables all exist already are marked too, with the table names as the reason. - Prints one line per migration,
MARK <name> — <reason>, orWOULD MARKin a dry run. - Writes the rows in one new batch, with
tinker --executeinside the container, and says how many. Nothing else in the database is touched.
Pitfalls
It only reads Schema::create
A renamed migration that alters a table instead of creating one is not found by --all-existing, and neither is one that creates its table through a raw statement. Read the failing migration, decide, and name it.
Marking a migration that really has not run
The row says it ran; the schema says otherwise, and the next release that depends on the change fails somewhere less obvious. --dry-run first, then compare the list against the error migrate gave you. Mark what it complained about, not what looks similar.
There is no tinker
The script runs through php artisan tinker. An app image that left laravel/tinker out answers Command "tinker" is not defined — add it back to the project before this can work.
With --remote this is production, and the rows are written before you can read the list twice. Run the dry run, read it, then run it again without.
After it finishes
Run the migration that failed again — grim migrate:mark-applied marks, it does not migrate. On a server that is grim deploy once more, or grim remote:artisan migrate --force if you would rather not rebuild anything. Locally, grim artisan migrate.
Related spells
grim deploy
Send an image to a server
Roll a pushed image tag out to one environment over SSH, verify the app answers, and fall back to the previous tag when it does not.
grim remote:artisan
Run artisan on the server
Run one artisan command inside the app container of the deployed project, from your own terminal.
grim artisan
Run artisan in the container
Run an artisan command inside the app container, where the app's PHP, extensions and environment are.