Flask-migrate: Can I delete a migration file?

Created on 28 Apr 2020  路  2Comments  路  Source: miguelgrinberg/Flask-Migrate

I arrived at the question, _Can I just delete a migration file_, because I did just that and found unexpected result.

Working on the Flask-Mega tutorial, I added a one new field to Model. I ran the command flask db migrate and made the first migration.

A few hours later I changed the schema yet again--delete new column, add different column. Then I applied a second flask db migrate. As suggested in the tutorial I inspected the migration file to find in the upgrade block: add new field; drop old field. Perfect.

I tried flask db upgrade and it failed. Ah! I made an error in the Model. Correct the Model.py file and what? Migrate again, over the mistake which was never applied?

KISS says the easiest fix was delete the migration file and reissue the flask db migrate command. Only now, there instruction to add new column is missing. I only see the command to drop the old field.

Is there some other setting now out of sync? Can I delete a migration file generated on top of an error?

question

Most helpful comment

It's not a simple question. In general the answer is yes, but there are some gotchas. I'll try to break it down.

  • If you run flask db migrate to generate your migration, and then change your mind before you run flask db upgrade then yes, it is 100% safe to delete the migration script and then generate a new migration later.

  • If you run flask db migrate, then flask db upgrade, then at that point your migration is the "current" migration, and the database has incorporated those changes. In this case to delete the migration you have to run flask db downgrade, and then your migration script is free and can be deleted.

  • If you delete a migration script that is in the migration history, but is not the current migration, then nothing will appear broken, but you may have trouble upgrading a database that is at the deleted migration or an earlier one. Some people delete the oldest migration scripts once they know they'll never need to be used again as part of an upgrade. Those who use this technique to prune their migration history are forced to create new databases using db.create_all() since it is not possible to run the entire migration history once the older scripts are deleted.

  • The trickiest case is when you generate a migration, then do the upgrade and something within that upgrade fails. The problem here is that on some databases schema changes are not considered part of transactions and aren't removed when the transaction is rolled back, so your database may have some of the changes in the migration script already applied. The way to fix this situation is a bit complex:

    • first figure out how much of the migration did actually execute.
    • change the downgrade() to only undo those changes that were applied, remove everything else.
    • make upgrade() an empty function
    • run flask db upgrade again to force Alembic to go through with the now empty migration.
    • run flask db downgrade to undo the partial changes
    • now you can delete the migration and start over

Hope this helps!

All 2 comments

It's not a simple question. In general the answer is yes, but there are some gotchas. I'll try to break it down.

  • If you run flask db migrate to generate your migration, and then change your mind before you run flask db upgrade then yes, it is 100% safe to delete the migration script and then generate a new migration later.

  • If you run flask db migrate, then flask db upgrade, then at that point your migration is the "current" migration, and the database has incorporated those changes. In this case to delete the migration you have to run flask db downgrade, and then your migration script is free and can be deleted.

  • If you delete a migration script that is in the migration history, but is not the current migration, then nothing will appear broken, but you may have trouble upgrading a database that is at the deleted migration or an earlier one. Some people delete the oldest migration scripts once they know they'll never need to be used again as part of an upgrade. Those who use this technique to prune their migration history are forced to create new databases using db.create_all() since it is not possible to run the entire migration history once the older scripts are deleted.

  • The trickiest case is when you generate a migration, then do the upgrade and something within that upgrade fails. The problem here is that on some databases schema changes are not considered part of transactions and aren't removed when the transaction is rolled back, so your database may have some of the changes in the migration script already applied. The way to fix this situation is a bit complex:

    • first figure out how much of the migration did actually execute.
    • change the downgrade() to only undo those changes that were applied, remove everything else.
    • make upgrade() an empty function
    • run flask db upgrade again to force Alembic to go through with the now empty migration.
    • run flask db downgrade to undo the partial changes
    • now you can delete the migration and start over

Hope this helps!

I was only looking for a part of that long answer, but the whole thing is really helpful. Thanks for being thorough!

Was this page helpful?
0 / 5 - 0 ratings