Django’s approach is to run all the migrations, from the migration files, if the database gets wiped clean. In other words, if you’re developing on your local machine, you can just drop the DB and start new (or if using SQLite, just delete a file), and after running migrations, you never have to worry about whether all the necessary files are in sync with the database. As Neo might say:“there is no spoon…” seriously, structure.sql is simply not needed, so you won’t find yourself making creative use of git reset/checkout on a specific file as you’re iterating.
To answer an earlier question you had, Django’s “makemigrations” command tries its best to help you avoid having to manually edit migration files; if you rename a field in models.py, it’s usually smart enough to ask you, at the command line, if you renamed it, and proceed to make the migration file for you. Of course, for advanced migrations the command can only take you so far, but again, if you’re trying to iterate quickly, you really need to experience Django’s ORM and DB tools to be able to appreciate them fully.
Regarding changesets, I love the functional API, and at the same time I wish we could automatically derive a “default_changeset” function from the schema itself for straightforward cases, and then let devs run diverging validations in their own changeset functions. Maybe an interesting idea to explore with a macro?
By the way, I’m a huge fan of your work, and hope I get the opportunity to work with Elixir for a long time. Any criticisms or comparisons are to try to bring improvements to the ecosystem I love. :)