{"id":3460,"library":"django-linear-migrations","title":"Django Linear Migrations","description":"django-linear-migrations is a Django app that enforces a linear migration history in your project, preventing common issues caused by concurrent migration development and merge migrations. It achieves this by introducing `max_migration.txt` files for each app, which will conflict in version control (e.g., Git) if multiple branches add migrations concurrently. The library, currently at version 2.19.0, is actively maintained with frequent releases.","status":"active","version":"2.19.0","language":"en","source_language":"en","source_url":"https://github.com/adamchainz/django-linear-migrations","tags":["django","migrations","development","git","workflow","ci"],"install":[{"cmd":"pip install django-linear-migrations","lang":"bash","label":"Install from PyPI"}],"dependencies":[{"reason":"Core framework dependency. Supports Django 4.2 to 6.0.","package":"Django","optional":false},{"reason":"Runtime environment. Supports Python 3.10 to 3.14.","package":"Python","optional":false},{"reason":"Used by `rebase_migration` command for formatting modified migration files, if available.","package":"black","optional":true}],"imports":[{"note":"Add 'django_linear_migrations' to your Django project's INSTALLED_APPS setting.","symbol":"django_linear_migrations","correct":"INSTALLED_APPS = [\n    # ...\n    'django_linear_migrations',\n    # ...\n]"},{"note":"When overriding Django's built-in `makemigrations` or `squashmigrations` with django-linear-migrations, your custom command must subclass `django_linear_migrations.management.commands.makemigrations.Command` (or `squashmigrations.Command`). Ensure your app with the custom command is listed *before* `django_linear_migrations` in `INSTALLED_APPS`.","wrong":"from django.core.management.commands.makemigrations import Command","symbol":"Command","correct":"from django_linear_migrations.management.commands.makemigrations import Command as BaseCommand\n\nclass Command(BaseCommand):\n    # ... your custom logic\n    pass"}],"quickstart":{"code":"# 1. Install the library\npip install django-linear-migrations\n\n# 2. Add to INSTALLED_APPS in settings.py\n# settings.py\nINSTALLED_APPS = [\n    # ... your first-party apps first\n    'your_app_name',\n    'django_linear_migrations',\n    # ... other third-party apps\n]\n\n# Optional: Explicitly define first-party apps if auto-detection fails (e.g., with editable installs)\n# settings.py\n# FIRST_PARTY_APPS = ['your_app_name']\n# INSTALLED_APPS = FIRST_PARTY_APPS + ['django_linear_migrations', ...]\n\n# 3. Check automatic detection of first-party apps (dry run)\npython manage.py create_max_migration_files --dry-run\n\n# 4. Create initial max_migration.txt files\npython manage.py create_max_migration_files\n\n# Now, makemigrations will automatically update max_migration.txt, \n# and `git rebase` or `git merge` will expose migration conflicts.","lang":"python","description":"After installation, add `django_linear_migrations` to your `INSTALLED_APPS`. Run `create_max_migration_files --dry-run` to verify first-party app detection, then run `create_max_migration_files` to generate `max_migration.txt` files for your apps. These files track the latest migration and will cause Git conflicts if new migrations are created on divergent branches, forcing a linear history. The `rebase_migration` command can help resolve these conflicts automatically."},"warnings":[{"fix":"Update calls to the management commands (e.g., in CI scripts) to use the new underscore-separated names.","message":"In version 2.0.0, the management commands were renamed from using hyphens to underscores to make them importable and extensible. `create-max-migration-files` became `create_max_migration_files` and `rebase-migration` became `rebase_migration`.","severity":"breaking","affected_versions":">=2.0.0"},{"fix":"Upgrade your Python environment to 3.10 or a later supported version.","message":"As of version 2.19.0, support for Python 3.9 has been dropped. The library now requires Python 3.10 or newer.","severity":"breaking","affected_versions":">=2.19.0"},{"fix":"Explicitly define your first-party apps using the `FIRST_PARTY_APPS` setting in your `settings.py`. For example: `FIRST_PARTY_APPS = ['your_app_name', 'another_app']` and combine it into `INSTALLED_APPS`: `INSTALLED_APPS = FIRST_PARTY_APPS + ['django_linear_migrations', ...]`.","message":"Automatic detection of 'first-party' (project) apps can sometimes fail, especially with editable package installations (`pip install -e`). This can lead to `max_migration.txt` files being created for third-party apps.","severity":"gotcha","affected_versions":"all"},{"fix":"See the `imports` section for the correct subclassing pattern. Adjust `INSTALLED_APPS` order as necessary.","message":"If you override Django's built-in `makemigrations` or `squashmigrations` commands in your project, your custom command must subclass the version provided by `django-linear-migrations` to ensure its functionality. Additionally, your app containing the custom command must be listed *above* `django_linear_migrations` in `INSTALLED_APPS`.","severity":"gotcha","affected_versions":"all"},{"fix":"If your feature branch has multiple commits that create migrations, it's recommended to squash those commits into a single migration before rebasing your branch onto the main branch (e.g., using `git rebase -i --keep-base main`).","message":"The `rebase_migration` command does not currently support rebasing multiple migrations within the same app. Attempting this may lead to unexpected behavior or incomplete rebasing.","severity":"gotcha","affected_versions":"all"},{"fix":"After running `python manage.py rebase_migration <app_label>`, run your code formatter (e.g., Black, isort) on the modified migration files. If you use pre-commit hooks, remember that Git does not invoke hooks during rebase commits, so you might need to run `pre-commit run` manually on the changed files.","message":"The `rebase_migration` command does not guarantee that its edits to migration files will match your project's code style. It will attempt to format with Black if installed, but manual reformatting may still be needed.","severity":"gotcha","affected_versions":"all"}],"env_vars":null,"last_verified":"2026-04-11T00:00:00.000Z","next_check":"2026-07-10T00:00:00.000Z"}