Skip to main content

How to Remove the Last EF Core Migration

· 7 min read
Jagdish Kumawat
Founder @ Dewiride

You ran dotnet ef migrations add, looked at the result, and it's wrong: a missing setting, a typo in the name, a change you didn't mean to include. dotnet ef migrations remove undoes it cleanly, as long as the migration hasn't been applied. This guide removes an unapplied migration, shows the error when it was applied, and the two ways forward from there.

What Removing Does​

EF Core's tools reference says the command "Removes the last migration, rolling back the code changes that were done for the latest migration." That's three things: the migration's .cs file, its .Designer.cs file, and the change it made to the model snapshot.

The managing migrations page gives the typical case: "Sometimes you add a migration and realize you need to make additional changes to your EF Core model before applying it."

Prerequisites​

Step 1: Remove a Migration That Isn't Applied​

I added a unique index to a category name and created the migration, AddCategoryNameIndex. Reading it showed EF Core had also changed the column from longtext to varchar(255), a length nobody chose. The migration wasn't applied yet:

Output (dotnet ef migrations list, last lines)
20261103043401_CreateCatalogTables
20261103043533_LowercaseTableNames
20261103043612_AddCategoryNameIndex (Pending)

Remove it:

Terminal
dotnet ef migrations remove --project src/Dewiride.Inventory.Data --startup-project src/Dewiride.Inventory.Api
Output (the lines that matter)
Build started...
Build succeeded.
Removing migration '20261103043612_AddCategoryNameIndex'.
Reverting the model snapshot.
Done.

A terminal where dotnet ef migrations remove checks the database, then prints Removing migration '20261103043612_AddCategoryNameIndex', Reverting the model snapshot and Done.

Before removing, the command read __EFMigrationsHistory from the database to make sure the migration wasn't applied. Then it deleted both migration files and put the snapshot back. Your model code, the entity or configuration change you made, stays as it is: fix it, then add the migration again.

Step 2: Try to Remove an Applied Migration​

Here's what happens with a migration that is applied, MakeDescriptionRequired:

Output
Build started...
Build succeeded.
The migration '20261103044430_MakeDescriptionRequired' has already been applied to the database. Revert it and try again. If the migration has been applied to other databases, consider reverting its changes using a new migration instead.

EF Core refuses, because removing the files would leave the database with changes no migration describes. The message gives both ways forward.

Step 3: Revert, Then Remove​

On your own development database, revert first, by updating the database to the migration before it:

Terminal
dotnet ef database update RestrictCategoryDelete --project src/Dewiride.Inventory.Data --startup-project src/Dewiride.Inventory.Api
Output (the lines that matter)
Reverting migration '20261103044430_MakeDescriptionRequired'.
ALTER TABLE `products` MODIFY `Description` longtext NULL;
DELETE FROM `__EFMigrationsHistory`
WHERE `MigrationId` = '20261103044430_MakeDescriptionRequired';
Done.

The migration's Down method ran, and its history row was deleted, so it's pending again. Now remove works:

Output (dotnet ef migrations remove)
Removing migration '20261103044430_MakeDescriptionRequired'.
Reverting the model snapshot.
Done.

Remember to undo the model change too; here, Description went back to string?. has-pending-model-changes then confirmed the code and the migrations agreed again.

Step 4: Or Do Both with --force​

The docs offer a shortcut: "Alternatively, --force performs both steps". The tools reference describes it as "Revert the latest migration, rolling back both code and database changes". A throwaway migration, applied and then removed in one command:

Terminal
dotnet ef migrations remove --force --project src/Dewiride.Inventory.Data --startup-project src/Dewiride.Inventory.Api
Output (the lines that matter)
Acquiring an exclusive lock for migration application. See https://aka.ms/efcore-docs-migrations-lock for more information if this takes too long.
Reverting migration '20261103045409_TryLongerCategoryName'.
ALTER TABLE `categories` MODIFY `Name` varchar(100) NOT NULL;
Removing migration '20261103045409_TryLongerCategoryName'.
Reverting the model snapshot.
Done.

A terminal where dotnet ef migrations remove --force acquires the migration lock, reverts TryLongerCategoryName by modifying the column back to varchar(100), removes the migration and reverts the model snapshot.

It reverted the database change and removed the files. The lock line is EF Core 9 and later protecting against two migrations running at once.

When Not to Remove​

The docs warn: "Avoid removing any migrations which have already been applied to production databases. Doing so means you won't be able to revert those migrations from the databases, and may break the assumptions made by subsequent migrations." Once a migration has reached a shared or production database, leave it in place and create a new migration that undoes it, as the error message suggests. Removing is for your own work in progress.

Common Mistakes​

MistakeWhat happensDo this instead
Deleting the migration files by handThe snapshot still contains the change; the next migration is wrongUse dotnet ef migrations remove
Removing an applied migration on a shared databaseOther databases keep changes no migration describesAdd a new migration that undoes it
Forgetting to undo the model change after removingThe next migrations add creates the same migration againFix or undo the model first
Removing a migration that isn't the last oneNot possible: the command only removes the lastRemove from the newest down, or add a corrective migration

Troubleshooting​

SymptomLikely causeFix
The migration '…' has already been applied to the database.It's appliedRevert first, or --force on a development database
The revert failsThe Down method can't undo the data as it is nowFix Down, then revert
remove can't reach the databaseThe database is downStart it; with --force, the tools fall back to removing only the code

The last row comes from the reference's description of --force: it "Continues to roll back only the code changes if an error occurs while connecting to the database."

FAQ​

Does removing a migration delete data?​

No. Removing only touches files. Reverting, with database update or --force, runs the migration's Down method, which can drop columns or tables and their data.

Can I remove several migrations?​

One at a time: each remove takes the newest. To undo several applied ones, revert to the oldest one you want to keep, then run remove once per migration.

Conclusion​

dotnet ef migrations remove deletes the last migration's files and reverts the snapshot, after checking that the migration isn't applied. When it is, revert first with dotnet ef database update <previous migration> and then remove, or use --force to do both on a development database. Once a migration has reached a shared database, don't remove it: add a new migration that undoes it.

Additional Resources​

Stay Updated

Subscribe to our newsletter for the latest tutorials, tech insights, and developer news.

By subscribing, you agree to our privacy policy. Unsubscribe at any time.