155

I've accumulated quite a few migrations using South (0.7) and Django (1.1.2) which are starting to consume quite a bit of time in my unit tests. I would like to reset the baseline and start a fresh set of migrations. I've reviewed the South documentation, done the usual Google/Stackoverflow searching (e.g. "django south (reset OR delete OR remove) migration history") and haven't found anything obvious.

One approach I've contemplated would involve "starting over" by "removing" South or "clearing" the history manually (e.g. clear the db table, remove migration files from the migrations director) and just re-run,

./manage.py schemamigration southtut --initial

So, if anyone has done this before and has some tips/suggestions they would be greatly appreciated.

skaffman
  • 398,947
  • 96
  • 818
  • 769
Glenn Snyder
  • 1,768
  • 3
  • 12
  • 9
  • sometimes you need to manually add `__init__.py` to `appname/migrations` – laike9m Jan 12 '14 at 17:16
  • 2
    How do you reset the migrations in 1.7 (with the built-in migration)? – Timo Nov 22 '14 at 08:56
  • 1
    @Timo : https://docs.djangoproject.com/en/dev/topics/migrations/#squashing-migrations could be an approach. You can also just remove your *migrations/* directories and re-issue `./manage.py makemigrations` but bad things will happen if you don't start from a fresh db... – Jocelyn delalande Dec 17 '14 at 10:11
  • I think `squashmigrations` is the right answer – Julio Marins May 20 '16 at 19:05

7 Answers7

187

If you need to selectively (for just one app) reset migrations that are taking too long, this worked for me.

rm <app-dir>/migrations/*
python manage.py schemamigration <app-name> --initial
python manage.py migrate <app-name> 0001 --fake  --delete-ghost-migrations

Don't forget to manually restore any dependencies on other apps by adding lines like depends_on = (("<other_app_name>", "0001_initial"),("<yet_another_app_name>", "0001_initial")) to your <app-dir>/migrations/0001_initial.py file, as the first attribute in your migration class just below class Migration(SchemaMigration):.

You can then ./manage.py migrate <app-name> --fake --delete-ghost-migrations on other environments, per this SO answer. Of course if you fake the delete or fake the migrate zero you'll need to manually delete any left-over db tables with a migration like this.

A more nuclear option is to ./manage.py migrate --fake --delete-ghost-migrations on the live deployment server followed by a [my]sqldump. Then pipe that dump into [my]sql on the environments where you need the migrated, fully-populated db. South sacrilege, I know, but worked for me.

Community
  • 1
  • 1
hobs
  • 18,473
  • 10
  • 83
  • 106
  • 2
    What I really want is "take models.py as gospel, and make me a clean on from that point on". Thus retaining the ability to set a deployment up from scratch, or work from an existing deployment. – Bryce Jan 04 '14 at 00:08
  • 1
    That's what this does. – hobs Jan 04 '14 at 00:22
  • 2
    @hobs I was getting a `DependsOnUnknownMigration` while faking the new initial migration. Thanks to your comment, I could figure out that I should update the `depends_on` statement wherever it refers to this app. This is really the best answer here. Thanks! :) – manu Feb 25 '14 at 13:08
121

EDIT - I'm putting a comment below at the top of this as it's important to read it before the > accepted answer that follows @andybak

@Dominique: Your advice regarding manage.py reset south is dangerous and may destroy the database if there are any third party apps using south in the project, as pointed out by @thnee below. Since your answer has so many upvotes I'd really appreciate it if you could edit it and add at least a warning about this, or (even better) change it to reflect @hobs approach (which is just as convenient, but doesn't affect other apps) - thanks! – chrisv Mar 26 '13 at 9:09

Accepted answer follows below:

First, an answer by the South author:

As long as you take care to do it on all deployments simultaneously, there shouldn't be any problem with this. Personally, I'd do:

    rm -r appname/migrations/ 
    ./manage.py reset south 
    ./manage.py convert_to_south appname 

(Notice that the “reset south” part clears migration records for ALL apps, so make sure you either run the other two lines for all apps or delete selectively).

The convert_to_south call at the end makes a new migration and fake-applies it (since your database already has the corresponding tables). There's no need to drop all the app tables during the process.

Here's what I'm doing on my dev + production server when I need to get rid of all these unneeded dev migrations:

  1. Make sure we have the same DB schema on both sides
  2. delete every migrations folder on both sides
  3. run ./manage.py reset south (as the post says) on both sides = clears the south table *
  4. run ./manage.py convert_to_south on both sides (faking 0001 migration)
  5. then I can re-start to make migrations and push the migrations folders on my server

* except if you want to clean only one app among others, if so you'll need to edit your south_history table and delete only the entries about your app.

Andy Baker
  • 21,158
  • 12
  • 58
  • 71
Dominique Guardiola
  • 3,431
  • 2
  • 22
  • 22
  • 2
    Just for the record, the South author's response was as follows: As long as you take care to do it on all deployments simultaneously, there shouldn't be any problem with this. Personally, I'd do: rm -r appname/migrations/ ./manage.py reset south ./manage.py convert_to_south appname (Notice that the "reset south" part clears migration records for ALL apps, so make sure you either run the other two lines for all apps or delete selectivey). – Adriaan Tijsseling Nov 07 '11 at 14:53
  • 2
    Note also that if you drop the tables, then you need `manage.py schemamigration app name --initial` instead of convert_to_south. – Adriaan Tijsseling Nov 07 '11 at 15:44
  • 7
    As of Django 1.5, the "reset" management command is gone. Instead, you'll want to do something roughly like `south.models.MigrationHistory.objects.all().delete()`. – Andrew B. Mar 01 '13 at 14:53
  • 13
    @Dominique: Your advice regarding `manage.py reset south` is **dangerous** and **may destroy the database** if there are any third party apps using south in the project, as pointed out by @thnee below. Since your answer has so many upvotes I'd really appreciate it if you could edit it and add at least a warning about this, or (even better) change it to reflect @hobs approach (which is just as convenient, but doesn't affect other apps) - thanks! – chrisv Mar 26 '13 at 09:09
  • 3
    Why was this so highly upvoted? You should almost NEVER completely delete your south_migrationhistory table. That would completely screw up any dependent apps with migrations you don't want to touch. Hob's answer is the correct one. – Cerin May 22 '13 at 15:01
  • @Cerin isn't why the comment said to "notice that the “reset south” part clears migration records for ALL apps, so make sure you either run the other two lines for all apps or delete selectively", or do you pose a different concern? – Nick T Jan 11 '14 at 00:03
  • Along with @chrisv's comment, it should made clearer that `reset south` isn't just dangerous for third-party apps. _It's going to erase the migration history of all of your project's apps._ @hobs has a best solution per app. – Jamey Sep 26 '14 at 01:20
  • When I tried "./manage.py reset south", I got Unknown command: 'reset' Type 'manage.py help' for usage. – Casey Perkins Jan 13 '16 at 16:08
54

Thanks to the answers by Dominique Guardiola and hobs, it helped me solve a hard problem. However there are a couple of issues with the solution, here is my take on it.

Using manage.py reset south is not a good idea if you have any third party apps that uses South, for example django-cms (basically everything uses South).

reset south will delete all migration history for all apps that you have installed.

Now consider that you upgrade to the latest version of django-cms, it will contain new migrations like 0009_do_something.py. South will surely be confused when you try to run that migration without having 0001 through 0008 in the migration history.

It is much better/safer to selectively reset only the apps that you are maintaining.


First of all, make sure that your apps don't have any desync between migrations on disk, and migrations that have been executed on the database. Otherwise there will be headache.

1. Delete migration history for my apps

sql> delete from south_migrationhistory where app_name = 'my_app';

2. Delete migrations for my apps

$ rm -rf my_app/migrations/

3. Create new initial migrations for my apps

$ ./manage.py schemamigration --initial my_app

4. Fake execute the initial migrations for my apps

This inserts the migrations into south_migrationhistory without touching actual tables:

$ ./manage.py migrate --fake my_app

Step 3 and 4 is actually just a longer variant of manage.py convert_to_south my_app, but I prefer that extra control, in such delicate situation as modifying the production database.

thnee
  • 5,817
  • 3
  • 27
  • 23
  • 2
    I edited my answer to incorporate fixes for the problems you found (just guessing at them based on your answer), and tested it on a production database with millions of rows. – hobs Apr 09 '13 at 20:47
  • 2
    This is pretty much what we're doing. If you use --delete-ghost-migrations option at step 4, you can leave out step 1. – tobych Jul 29 '13 at 23:55
  • You should specify the app names explicitly in `./manage.py migrate --fake` if you don't want to fake migrate other apps that have migrations pending. – wadim Nov 27 '13 at 13:46
  • 2
    @wadim Hence step 0: "make sure that you have no desync between migrations on disk, and migrations that have been executed on the database". – thnee Nov 28 '13 at 08:33
  • @thnee Right. It's probably worth mentioning that you're refering to all installed apps in step 0. Do you know of an easy way to perform step 0 though? – wadim Nov 28 '13 at 09:08
  • @thnee could you clarify the 'delete from', specifying the tool used? – Bryce Jan 04 '14 at 00:11
  • @Bryce 'delete from' is raw SQL executed in the database shell. – tadasajon Feb 25 '14 at 02:35
  • What about datamigrations? – tutuca Dec 11 '14 at 19:50
7

Like thnee (see her answer), we're using a gentler approach to the South author's (Andrew Godwin) suggestion quoted elsewhere here, and we're separating what we do with the code base from what we do to the database, during deployment, because we need the deployments to be repeatable:

What we do in the code:

# Remove all the migrations from the app
$ rm -fR appname/migrations
# Make the first migration (don't touch the database)
$ ./manage.py schemamigration appname --initial

What we do to the database once that code is deployed

# Fake the migration history, wiping out the rest
$ ./manage.py migrate appname --fake --delete-ghost-migrations
tobych
  • 2,941
  • 29
  • 18
  • I think I just did the same thing, but manually deleting database entries, rather than using --delete_ghoist-migrations. Your way is a bit nicer. – wobbily_col Dec 01 '14 at 16:51
1

If you are just working on the dev machine, I wrote a management command that does pretty much what Dominique suggested.

http://balzerg.blogspot.co.il/2012/09/django-app-reset-with-south.html

In contrast of the south author suggestion, this will NOT HARM other installed apps using south.

idanzalz
  • 1,740
  • 1
  • 11
  • 18
  • And if, unlike the author, you want to *keep* existing migrations (i.e. you want to reset the app as well as migration history, but keep the actual migrations), then you can try this: http://goo.gl/0ZnWm – mgalgs Nov 02 '12 at 05:45
1

Following is only if you want to reset all apps. Please backup your all databases prior to that work. Also note down your depends_on in initial files if there are any.

For once:

(1) find . -type d -name migrations -exec git rm -rf '{}' \;
(2) find . -type d -name migrations -exec rm -rf '{}' \;
(3) ./manage.py schemamigration <APP_NAME> --initial
(4) [GIT COMMIT]

Test bootstrapping your project before push. Then, for each local/remote machine, apply following:

(5) [GIT PULL]
(6) ./manage.py reset south
(7) ./manage.py migrate --fake

Do initial (3) for each app you want to re-involve. Note that, reset (6) will delete only migration history, therefore not harmful to libraries. Fake migrations (7) will put back migration history of any 3rd party apps installed.

hurturk
  • 5,214
  • 24
  • 41
0

delete necessary file from app folder

instance path

 cd /usr/local/lib/python2.7/dist-packages/wiki/south_migrations

wiki -is my app

Andrei Eremchuk
  • 155
  • 1
  • 1
  • 8