跳转到主要内容

确保您的迁移是线性的。

项目描述

https://img.shields.io/github/actions/workflow/status/adamchainz/django-linear-migrations/main.yml.svg?branch=main&style=for-the-badge https://img.shields.io/badge/Coverage-100%25-success?style=for-the-badge https://img.shields.io/pypi/v/django-linear-migrations.svg?style=for-the-badge https://img.shields.io/badge/code%20style-black-000000.svg?style=for-the-badge pre-commit

确保您的迁移历史是线性的。

有关背景信息,请参阅入门博客文章


通过我的书籍更聪明、更快速地工作,该书Boost Your Django DX涵盖了django-linear-migrations和其他许多工具,以提高您的开发体验。


需求

支持Python 3.8至3.12。

支持Django 3.2至5.1。

安装

首先, 使用pip安装

python -m pip install django-linear-migrations

其次, 将应用程序添加到您的INSTALLED_APPS设置

INSTALLED_APPS = [
    ...,
    "django_linear_migrations",
    ...,
]

应用程序依赖于重写内置的makemigrations命令。 如果您的项目有一个自定义 makemigrations 命令, 确保包含您的自定义命令的应用程序位于django_linear_migrations之上,并且您的命令是其Command类的子类

# myapp/management/commands/makemigrations.py
from django_linear_migrations.management.commands.makemigrations import (
    Command as BaseCommand,
)


class Command(BaseCommand):
    ...

第三, 检查第一方应用程序的自动检测。运行此命令

python manage.py create_max_migration_files --dry-run

此命令用于创建 max_migration.txt 文件(稍后将详细介绍)- 在干运行模式下,它会列出会创建此类文件的 app。它试图自动检测哪些 app 是第一方 app,即属于您的项目。自动检测检查 app 代码的路径,以查看它是否在虚拟环境中,但此检测有时可能会失败,例如在通过 -e 安装的可编辑包中。如果您看到列出的任何不属于您项目的 app,请定义 FIRST_PARTY_APPS 设置中第一方 app 标签的列表,并将其组合到 INSTALLED_APPS

FIRST_PARTY_APPS = []

INSTALLED_APPS = FIRST_PARTY_APPS + ["django_linear_migrations", ...]

(注意:Django 推荐您在项目中始终首先列出第一方 app,以便它们可以覆盖第三方和 contrib app 中的内容。)

第四,通过重新运行不带干运行标志的命令来为您的第一方 app 创建 max_migration.txt 文件。

python manage.py create_max_migration_files

将来,当您向项目添加新 app 时,您需要创建其 max_migration.txt 文件。根据需要将新 app 添加到 INSTALLED_APPSFIRST_PARTY_APPS,然后通过指定其标签重新运行创建新 app 的创建命令。

python manage.py create_max_migration_files my_new_app

用法

django-linear-migrations 帮助您处理 Django 项目,在这些项目中,可能同时进行多个添加迁移的分支。它强制您的 app 具有线性迁移历史,避免合并迁移及其可能导致的由迁移运行顺序不同而产生的问题。它通过使 makemigrations 记录每个 app 的 max_migration.txt 文件中的最新迁移名称来实现。在并行开发迁移的情况下,这些文件将在您的源代码控制工具(Git、Mercurial 等)中引起合并冲突。对于 app 的第一个合并迁移将阻止第二个合并,而不解决冲突。包含的 rebase_migration 命令可以帮助自动解决此类冲突。

系统检查

django-linear-migrations 随附一些系统检查,以验证您的 max_migration.txt 文件是否同步。这些包括

  • dlm.E001: <app_label> 的 max_migration.txt 文件不存在。

  • dlm.E002: <app_label> 的 max_migration.txt 包含多行。

  • dlm.E003: <app_label> 的 max_migration.txt 指向不存在的迁移 ‘<bad_migration_name>’。

  • dlm.E004: <app_label> 的 max_migration.txt 包含 ‘<max_migration_name>’,但最新迁移是 ‘<real_max_migration_name>’。

  • dlm.E005: 检测到冲突迁移;迁移图中存在多个叶子节点: <conflicting_migrations>

create_max_migration_files 命令

python manage.py create_max_migration_files [app_label [app_label ...]]

此管理命令为所有第一方 app 或指定的标签创建 max_migration.txt 文件。它在 django-linear-migrations 的初始安装中使用,也用于重新创建。

通过传递 --dry-run 标志,仅列出将要创建的 max_migration.txt 文件。

通过传递 --recreate 标志重新创建已存在的文件。这在修改迁移后使用合并或手动修改后可能很有用。

rebase_migration 命令

此管理命令可以帮助您解决迁移冲突。在 Git 中的冲突 "rebase" 操作之后,使用 app 的名称运行它以自动解决迁移冲突

$ python manage.py rebase_migration <app_label>

命令使用 max_migration.txt 文件中的冲突信息来确定要重新合并的迁移。它自动检测 Git 合并或重新合并操作是否正在进行,如果找不到 Git 仓库则假定重新合并。然后

  1. 重命名迁移

  2. 将其修改为依赖于您主分支的新迁移

  3. 更新 max_migration.txt

如果已安装 Black,则命令将使用它格式化更新的迁移文件,就像 Django 内置的迁移命令(从版本 4.1+)一样。下面有一些示例和注意事项。

请注意,重新合并迁移可能并不总是 正确 的做法。如果您的主分支和功能分支上的迁移都影响了相同的模型,将迁移重新合并到末尾可能没有意义。然而,这种并行更改通常会导致模型文件或其他源代码部分发生冲突。

工作示例

假设您在一个名为 titles 的功能分支上处理项目中的 books 应用程序,并创建了一个名为 0002_longer_titles 的迁移。同时,您的 main 分支已经合并了一个包含不同 2 号迁移的提交,该迁移名为 0002_author_nicknames。多亏了 django-linear-migrations,max_migration.txt 文件将显示为功能分支和主分支之间的冲突。

通过切换到功能分支 titles 并迁移到最后一个公共迁移来撤销您的本地数据库中的新迁移,以此开始修复。这是必要的,因为重新合并后它将被重命名并被视为未应用。

$ git switch titles
$ python manage.py migrate books 0001

然后,获取最新代码

$ git switch main
$ git pull
...

接下来,将 titles 分支基于最新代码进行重新合并。在此过程中,Git 将检测到 max_migration.txt 上的冲突。

$ git switch titles
$ git rebase main
Auto-merging books/models.py
CONFLICT (content): Merge conflict in books/migrations/max_migration.txt
error: could not apply 123456789... Increase Book title length
Resolve all conflicts manually, mark them as resolved with
"git add/rm <conflicted_files>", then run "git rebase --continue".
You can instead skip this commit: run "git rebase --skip".
To abort and get back to the state before "git rebase", run "git rebase --abort".
Could not apply 123456789... Increase Book title length

此时,books 应用程序的 max_migration.txt 内容可能看起来像这样

$ cat books/migrations/max_migration.txt
<<<<<<< HEAD
0002_author_nicknames
=======
0002_longer_titles
>>>>>>> 123456789 (Increase Book title length)

此时,使用 rebase_migration 自动修复 books 迁移历史记录

$ python manage.py rebase_migration books
Renamed 0002_longer_titles.py to 0003_longer_titles.py, updated its dependencies, and updated max_migration.txt.

这将在迁移历史记录的末尾放置冲突迁移。它将适当地重命名文件,修改其 dependencies = [...] 声明,并适当地更新 max_migration.txt 中命名的迁移。

之后,您应该可以继续重新合并

$ git add books/migrations
$ git rebase --continue

然后迁移本地数据库,以便您继续开发

$ python manage.py migrate books
Operations to perform:
  Target specific migration: 0003_longer_titles, from books
Running migrations:
  Applying books.0002_author_nicknames... OK
  Applying books.0003_longer_titles... OK

代码格式化

rebase_migration 不能保证其编辑与您的代码风格一致。如果您使用像 Black 这样的格式化程序,您会在应用 rebase_migration 后运行它。

如果您使用 pre-commit,请注意,Git 在重新合并提交期间不会调用钩子。您可以通过 pre-commit run 在更改的文件上手动运行它。

包含多个提交的分支

想象一下与上面相同的示例,但您的功能分支有几个提交正在编辑迁移。这次,在将您的功能分支重新合并到最新的 main 分支之前,将功能分支上的提交压缩在一起。这样,rebase_migration 就可以在冲突发生时编辑迁移文件。

您可以使用以下命令进行此操作

$ git rebase -i --keep-base main

这将打开 Git 的 交互式模式 文件。编辑此文件,使每个第一个提交之后的提交都被压缩,方法是每行以“s”开头。然后关闭文件,重新合并将执行。

在此操作之后,您可以像前面的示例一样将分支重新合并到最新的 main 分支。

包含多个迁移的分支

rebase_migration 目前不支持将多个迁移(在同一应用程序中)进行变基。这是一个开放的功能请求,但不是优先事项,因为通常一次限制一个迁移的更改是一个好主意。在变基之前,请考虑将迁移合并为一个。

灵感

我在多个地方看到过类似于 django-linear-migrations 实现的技术,这成为了整合这个包的灵感。我的前客户 Pollen 和当前客户 ev.energy 都有实现。这篇文章 Doordash 博客文章 介绍了一个类似的系统,该系统使用单个文件来跟踪最新迁移。还有一个名为 django-migrations-git-conflicts 的包,其工作方式相当类似。

项目详情


下载文件

下载您平台的文件。如果您不确定选择哪个,请了解更多关于 安装包 的信息。

源分布

django_linear_migrations-2.13.0.tar.gz (23.2 kB 查看哈希值)

上传时间

构建分布

django_linear_migrations-2.13.0-py3-none-any.whl (19.2 kB 查看哈希值)

上传时间 Python 3

支持者

AWS AWS 云计算和安全赞助商 Datadog Datadog 监控 Fastly Fastly CDN Google Google 下载分析 Microsoft Microsoft PSF 赞助商 Pingdom Pingdom 监控 Sentry Sentry 错误记录 StatusPage StatusPage 状态页面