92

(I know there is a title the same as this, but the question is different).

I have managed to get my development machine migrations and production migrations out of sync.

I have a Django app which was using South. I had my own workflow that worked fine (it probably wasn't the correct way to do things, but I had no problems with it).

Basically I have a script that copies the production database dump to my development machine. It also copied the migration files. That way the two were in synch, and I could run South commands as normal.

Now I have upgraded to 1.7, and started using migrations. When I use my previous workflow (copy database dump, and migration files from production), it is not detecting changes on my development machine.

I have read through the migrations document, and I see that the correct way to use it is to

  1. run "make migrations" and "migrate" on my development machine.
  2. run "migrate" on my devlopemnt machine to actually make the database changes
  3. Copy changes over, including migration files.
  4. run "migrate" on the production machine. (without the "makemigrations" step)

Anyway. It is all a mess now. I would like to "reset" my migrations and start from scratch, doing things properly from now on.

What do I need to do?

  1. Delete the contents of the migration table (on both machines)?
  2. Delete the contents of the migration folder? (Including the init.py file).
  3. Start the migrations as per the documentation for a new one.

Have I missed anything? Is there a reason why copying everything from production(database and migration files) doesn't detect any changes on my development machine afterwards

wobbily_col
  • 11,390
  • 12
  • 62
  • 86
  • 1
    Just delete the migrations folder and make new ones... – rnevius Mar 25 '15 at 10:50
  • 1
    Done that, it doesn't detect changes. Plus you need to keep the database table in sync with the migrations folder. I was wondering if there is anything else. – wobbily_col Mar 25 '15 at 15:40

13 Answers13

129

I would just do the following on both the environments (as long as the code is the same)

  1. Delete your migrations folder
  2. DELETE FROM django_migrations WHERE app = <your app name> . You could alternatively just truncate this table.
  3. python manage.py makemigrations
  4. python manage.py migrate --fake

After this all your changes should get detected across environments.

harshil
  • 1,655
  • 1
  • 11
  • 7
  • This sounds more or less like what I did in the end. I tried deleting (well actually renaming the django_migrations table). Then I discovered some app migrations depended on others, so I repopulated those entries in the new django_migrations table. – wobbily_col Mar 26 '15 at 13:15
  • I've seen so many answers to similar questions that make this more complicated than it needs to be. This is the way to do it. Clean and simple. – Eric Ressler Apr 07 '16 at 21:20
  • 3
    Now Django won't detect any new changes; ie adding a table. any ideas? – Turtles Are Cute Apr 14 '16 at 18:12
  • 41
    I did this but, like Turtles Are Cute, kept getting "No changes detected" (Django 1.10). The solution was to run `makemigrations` specifying the app. e.g., `python manage.py makemigrations polls` if your app is called `polls`. – Phil Gyford Oct 10 '16 at 13:52
  • `python manage.py flush --no-input` to avoid no action after typing yes to continue – Abdallah Okasha Jun 30 '18 at 23:45
  • if you delete the directory you should either specify the app name or recreate the directory. (the migrations directory) – yukashima huksay Feb 11 '19 at 19:05
  • @PhilGyford thank you very much Phil. I ran into the same problem until I found your comment – Austin not from Boston Apr 02 '20 at 18:39
  • Will this work also if the current database differs from models.py? For example if a few extra fields has been added in models.py but not yet in the database – embe Sep 07 '21 at 09:33
  • Just to add, if you want to see the changes in the database schema also. First, delete any tables created against the old migrations, and then `migrate` without the `--fake` option. – Muhammad Zubair Jan 25 '22 at 20:16
  • [django-reset-migrations](https://pypi.org/project/django-reset-migrations/) is a light package with a Django command that do just the same as this answer suggests – artu-hnrq Jan 28 '23 at 01:48
107

Run

python manage.py migrate your_app zero

This will drop all tables from your_app

If you want, since you said you want to start over, you can delete your migrations folder, or maybe rename the folder, create a new migrations folder and run

python manage.py makemigrations your_app
python manage.py migrate your_app

Just like south, you can always go back and forth...

# Go to the first migration
python manage.py migrate your_app 0001

# Go to the third migration
python manage.py migrate your_app 0003

So imagine that your 4th migration is a mess... you can always migrate to the 3rd, remove the 4th migration file and do it again.

Note:

This one of the reasons your models should be in different apps. Say you have 2 models : User and Note. It's a good practice to create 2 apps: users and notes so the migrations are independent from each other.

Try not use a single application for all your models

brunofitas
  • 2,983
  • 1
  • 20
  • 26
  • 4
    Drop all tables, on my app? That is definitely not the solution am looking for. Or have I misunderstood your wording? – wobbily_col Mar 25 '15 at 10:59
  • app, not project... anyway, check my edit... zero will clear everything on the app, not the project, before 0001... – brunofitas Mar 25 '15 at 11:01
  • Thanks for the update. I have tried deleting the migrations folder, but none of the changes get detected after that. – wobbily_col Mar 25 '15 at 11:03
  • did you migrate back to zero before you did that? – brunofitas Mar 25 '15 at 11:04
  • 1
    Ran zero, and nothing is detected or changed. – wobbily_col Mar 25 '15 at 11:16
  • I guess you're confusing project with app. You project has several apps. for example "auth" is one. "auth" has "auth_user" and "auth_group" tables, right? If you run "python manage.py migrate auth zero" all tables from the app "auth" will be removed from the database. The same happens with other apps. Imagine you have an app called "notes". this would have a Model Note. Migrating this app would create a table "notes_note". If you run "python manage.py migrate notes zero", the table "notes_note" will be removed, but all the rest stays. Do you have many apps, or every model in one app ? – brunofitas Mar 25 '15 at 11:21
  • Let us [continue this discussion in chat](http://chat.stackoverflow.com/rooms/73752/discussion-between-brunofitas-and-wobbily-col). – brunofitas Mar 25 '15 at 11:35
36

A minor variation on harshil's answer:

$ manage.py migrate --fake <appname> zero
$ rm -rf migrations
$ manage.py makemigrations <appname>
$ manage.py migrate --fake <appname>

This will ...

  • pretend to rollback all of your migrations without touching the actual tables in the app
  • remove your existing migration scripts for the app
  • create a new initial migration for the app
  • fake a migration to the initial migration for the app
rrauenza
  • 6,285
  • 4
  • 32
  • 57
9

To reset all migrations and start all over, you can run the following:

1. Reset all migration

python manage.py migrate <app_name> zero

ℹ️ If this is causing you issues you can add the --fake flag to the end of the command.

2. Create the migration

python manage.py makemigrations <app_name>

ℹ️ Only do this step if you deleted or altered the migrations files

3. Migrate

python manage.py migrate <app_name>

⚠️ if you added the --fake command to step # 1 you will need to add --fake-initial to the migrate command so python manage.py migrate <app_name> --fake-initial

KhaledMohamedP
  • 5,000
  • 3
  • 28
  • 26
3

I had a similar issue to this but when testing some of these same solutions using python manage.py showmigrations I noticed I got the same error.

Eventually I found this post which helped me realize I was overcomplicating things and essentially had two User models defined.

gun.go
  • 113
  • 5
3

This works for me

Step1:
delete all "migrations" folders in all apps

Step2:
create a brand new app.
python manage.py justTestApp.
Copy the new "migrations" folder of the new app to all apps

Step3:
delete the "db.sqlite3" file.
delete the "justTestApp" folder

Step4:
python manage.py makemigrations
python manage.py migrate

T H
  • 423
  • 4
  • 7
3

If you want a completely clean start, you're gonna wanna drop the DB. Which means then to recreate it, add privileges, re-generate all the migrations, re-run them and create a superuser.

Good news is that you can easily make all this into a single/few line commands.

Fresh migration files

If you delete the whole folders, you're gonna have to run the makemigrations command mentioning all the app names. That's a hassle if you do this often. To have Django see the apps that need migrations, you'll wanna keep the migrations folder and the __init__.py inside them.

Here's a bash command for that:

find . -path "*migrations*" -not -regex ".*__init__.py" -a -not -regex ".*migrations" | xargs rm -rf

Then the usual (this should create migrations for all the apps that had migrations before):

python manage.py makemigrations

Resetting the DB

For SQLite just delete the DB file.

For PostgreSQL run this in the console:

psql -c "drop database <db_name>;"
psql -c "create database <db_name>;"
psql -c "grant all on database <db_name> to <db_user>;"

And then finally re-run migrations with

python manage.py migrate

Superuser

You're gonna obviously be missing a superuser, so you might wanna also do:

python manage.py createsuperuser

No-input way of doing that is piping python code into the shell:

echo "from django.contrib.auth import get_user_model; User = get_user_model(); User.objects.create_superuser('admin', 'badmin@myproject.com', 'pa$$w0rd')" | python manage.py shell

Generally speaking about these very common actions - Do yourself a favour and write a bit of bash. It has saved me many, many accumulated hours over the years of working with not only Django. Because even better than a oneline command is having a whole utility file to store more of these handy functions. Then you can just run something like:

django --reset_migrations
db --reset <my_db>
django --migrate

Or even aggregate that into a single line if you find yourself repeating the same few actions. Add this to your bashprofile

reset_django() {
    find . -path "*migrations*" -not -regex ".*__init__.py" -a -not -regex ".*migrations" | xargs rm -rf
    python manage.py makemigrations
    psql -c "drop database <db_name>;"
    psql -c "create database <db_name>;"
    psql -c "grant all on database <db_name> to <db_user>;"
    python manage.py migrate
    echo "from django.contrib.auth import get_user_model; User = get_user_model(); User.objects.create_superuser('admin', 'badmin@myproject.com', 'pa$$w0rd')" | python manage.py shell
}

My Django lite utilities for inspiration:

#!/bin/bash


django() {

    project_name=$(basename $PWD)
    project_path="$PWD"
    manage_path="${project_path}/${project_name}/manage.py"

    if [ ! -f $manage_path ] ; then  # No project/manage.py
        echo "Error: Could not locate Django manage.py file."
        return -1
    fi

    if [ $# -eq 0 ] ; then
        echo "Django project detected."
    fi

    while [ ! $# -eq 0 ]
        do
            case "$1" in

                --help | -h)
                        echo "Django shortcut, unknown commands are forwarded to manage.py"
                        echo "  -c, --check         Run Django manage.py check."
                        echo "  --req           Install requirements."
                        echo "  -r, --run           Run server."
                        echo "  -s, --shell         Run Django shell plus."
                        echo "  -sd, --shell            Run Django shell plus. Debug DB (print sql)"
                        echo ""
                    ;;

                --check | -c)
                        python $manage_path check
                    ;;

                --shell | -s)
                        python $manage_path shell_plus --bpython
                    ;;

                --shell | -sd)
                        python $manage_path shell_plus --bpython --print-sql
                    ;;

                --run | -r)
                        python $manage_path runserver
                    ;;

                --req)
                        pip install -r $project_path/requirements.txt
                    ;;

                --mig | -m)
                        python $manage_path makemigrations
                        python $manage_path migrate
                    ;;

                --reset_migrations)
                        find . -path "*migrations*" -not -regex ".*__init__.py" -a -not -regex ".*migrations" | xargs rm -rf
                        python $manage_path makemigrations
                        ;;

                *)
                    python $manage_path "$@"
                    ;;

            esac
            shift
        done

}
Jura Brazdil
  • 970
  • 7
  • 15
2

So this solution worked for me today.

  1. Drop the django migrations table called "django_migrations" (No need to drop the whole database - just the migration table.)

  2. Deleted all migrations files (e.g. 0002_auto.py, etc) from all your apps, leave the __init__.py files. You can use this code from Ahmed Bouchefra:

    find . -path "/migrations/.py" -not -name "init.py" -delete

    find . -path "/migrations/.pyc" -delete

(This find and delete code works only for linux. For Windows you have to delete your files manually.)

  1. Now run the following commands:

    python manage.py makemigrations
    
    python manage.py migrate --fake
    

django will create a new migration table and fake the initial migration into the table without touching your existing data. Enjoy.

Samsul Islam
  • 2,581
  • 2
  • 17
  • 23
1

Faced similar issue. This worked for me.

python manage.py migrate <app_name> zero --fake

python manage.py migrate <app_name>
Thomas Smyth - Treliant
  • 4,993
  • 6
  • 25
  • 36
  • Yes, I have a far better understanding of the migrations system now. It was a while ago that I asked this question. – wobbily_col Nov 09 '22 at 11:06
0

After you have resetted your unwanted migrations in your project, you can still have the issue of having these unwanted migrations in your test database (the one created by pytest).

You can reset the test database by adding the --create-db to your test command:

py.test path/to-tests.py --create-db
Michael van de Waeter
  • 1,473
  • 15
  • 29
0

As mentioned by @brunofitas, going back to the previous migration helped my case. I thereafter deleted the migrations from that point to the last one, ran makemigrations, migrated and I was done.

fakeMake
  • 738
  • 8
  • 18
0

you can directly delete the migrations folder and migrate it again.

if you want to delete all data from database and delete all the migration:

  1. delete the migrations folder
  2. delete sqlite / database
  3. migrate again

it will give you a fresh database without previous migrations

khalidswe
  • 16
  • 4
0

You can use django zero migrations now:

pip3 install django-zeromigrations

And run:

python3 manage.py zeromigrations
Amin
  • 2,605
  • 2
  • 7
  • 15