【发布时间】:2020-11-19 15:38:48
【问题描述】:
我应该在 .gitignore 文件中添加 Django 迁移文件吗?
由于迁移冲突,我最近遇到了很多 git 问题,并且想知道是否应该将迁移文件标记为忽略。
如果是这样,我将如何添加我的应用程序中的所有迁移,并将它们添加到 .gitignore 文件中?
【问题讨论】:
我应该在 .gitignore 文件中添加 Django 迁移文件吗?
由于迁移冲突,我最近遇到了很多 git 问题,并且想知道是否应该将迁移文件标记为忽略。
如果是这样,我将如何添加我的应用程序中的所有迁移,并将它们添加到 .gitignore 文件中?
【问题讨论】:
引用Django migrations documentation:
每个应用程序的迁移文件位于该应用程序内部的“迁移”目录中,旨在提交到其代码库并作为其代码库的一部分进行分发。您应该在您的开发机器上进行一次迁移,然后在您同事的机器、暂存机器以及最终的生产机器上运行相同的迁移。
如果您遵循此过程,您应该不会在迁移文件中遇到任何合并冲突。
在合并版本控制分支时,您仍然可能会遇到基于同一个父迁移的多个迁移的情况,例如如果向不同的开发人员同时引入迁移。解决这种情况的一种方法是引入 merge_migration。通常这可以通过命令自动完成
./manage.py makemigrations --merge
这将引入依赖于所有当前头部迁移的新迁移。当然,这仅在头部迁移之间没有冲突时才有效,在这种情况下,您将不得不手动解决问题。
鉴于这里有些人建议您不应该将迁移提交给版本控制,我想详细说明您实际上应该这样做的原因.
首先,您需要记录应用于生产系统的迁移。如果您将更改部署到生产并希望迁移数据库,则需要对当前状态的描述。您可以为应用于每个生产数据库的迁移创建单独的备份,但这似乎不必要地繁琐。
其次,迁移通常包含自定义的手写代码。并非总是可以使用./manage.py makemigrations 自动生成它们。
第三,代码审查应包括迁移。它们是对您的生产系统的重大更改,并且可能会出现很多问题。
简而言之,如果您关心您的生产数据,请检查您的迁移到版本控制。
【讨论】:
makemigrations some_app,不仅该成员控制的模型会受到影响,其他相关模型也会受到影响。也就是说,其他应用程序中的迁移文件(00*_*)将被更改。这会在向 GitHub 推送或从 GitHub 拉取时导致许多冲突问题。由于目前我们的系统还没有准备好生产,我们只是.gitignore 迁移文件。当系统投入生产时,我们仍然不知道如何解决它。有人有解决办法吗?
您可以按照以下流程进行操作。
您可以在本地运行makemigrations,这会创建迁移文件。将这个新的迁移文件提交到 repo。
在我看来,您根本不应该在生产环境中运行 makemigrations。您可以在生产环境中运行migrate,您将看到迁移是从您从本地提交的迁移文件中应用的。这样你就可以避免所有的冲突。
IN LOCAL ENV,创建迁移文件,
python manage.py makemigrations
python manage.py migrate
现在提交这些新创建的文件,如下所示。
git add app/migrations/...
git commit -m 'add migration files' app/migrations/...
在生产环境中,只运行以下命令。
python manage.py migrate
【讨论】:
migrate 和从不运行 makemigrations 非常好。从来没想过。
引自 2018 年文档 Django 2.0。 (两个单独的命令 = makemigrations 和 migrate)
有单独的命令来创建和应用的原因 迁移是因为您将迁移提交到您的版本控制 系统并将它们与您的应用程序一起发布;他们不仅让你 开发更容易,它们也可供其他开发人员使用 生产。
【讨论】:
TL;DR:提交迁移,解决迁移冲突,调整您的 git 工作流程。
感觉您需要调整 git 工作流程,而不是忽略冲突。
理想情况下,每个新功能都在不同的分支中开发,并通过拉取请求合并回来。
如果存在冲突,则无法合并 PR,因此需要合并其功能的人需要解决冲突,包括迁移。这可能需要不同团队之间的协调。
提交迁移文件很重要!如果发生冲突,Django might even help you solve those conflicts ;)
【讨论】:
我无法想象为什么你会遇到冲突,除非你以某种方式编辑迁移?这通常会以糟糕的方式结束 - 如果有人错过了一些中间提交,那么他们将不会从正确的版本升级,并且他们的数据库副本将被损坏。
我遵循的过程非常简单 - 每当您更改应用程序的模型时,您也会提交迁移,然后 迁移不会改变 - 如果您在模型,然后您更改模型并在更改的同时提交新的迁移。
在新建项目中,您通常可以在发布时删除迁移并使用 0001_ 迁移从头开始,但如果您有生产代码,则不能(尽管您可以将迁移压缩为一个)。
【讨论】:
通常使用的解决方案是,在将任何内容合并到 master 之前,开发人员必须拉取任何远程更改。如果迁移版本存在冲突,他应该将他的 本地 迁移(远程版本已由其他开发人员运行,并且可能在生产中运行)重命名为 N+1。
在开发过程中,不提交迁移可能没问题(但不要添加忽略,只是不要add 他们)。但是一旦投入生产,您将需要它们以使架构与模型更改保持同步。
然后您需要编辑该文件,并将dependencies 更改为最新的远程版本。
这适用于 Django 迁移,以及其他类似的应用程序(sqlalchemy+alembic、RoR 等)。
【讨论】:
如果您有用于开发、暂存和生产环境的单独数据库,请忽略迁移。对于开发。目的您可以使用本地 sqlite DB 并在本地进行迁移。 我建议您创建四个额外的分支:
Master - 无需迁移即可清洁新代码。没有人连接到这个分支。仅用于代码审查
发展 - 日常发展。推/拉接受。每个开发人员都在开发 sqlite DB
Cloud_DEV_env - 远程云/服务器 DEV 环境。只拉。在机器本地保留迁移,用于开发数据库的代码部署和远程迁移
Cloud_STAG_env - 远程云/服务器 STAG 环境。只拉。在机器本地保存迁移,用于 Stag 数据库的代码部署和远程迁移
Cloud_PROD_env - 远程云/服务器 DEV 环境。只拉。在机器本地保留迁移,用于Prod数据库的代码部署和远程迁移
注意事项: 2, 3, 4 - 迁移可以保存在仓库中,但应该有严格的合并拉取请求的规则,所以我们决定找一个人,负责部署,所以唯一拥有所有迁移文件的人 - 我们的部署者.每次我们对模型进行任何更改时,他都会保留远程数据库迁移。
【讨论】:
在 git 中有一堆迁移文件很麻烦。迁移文件夹中只有一个文件是您不应忽略的。该文件是 init.py 文件,如果忽略它,python 将不再在目录中查找子模块,因此任何导入模块的尝试都会失败。所以问题应该是如何忽略除了 init.py 之外的所有迁移文件? 解决方案是: 将 '0*.py' 添加到 .gitignore 文件中,它可以完美地完成工作。
希望这对某人有所帮助。
【讨论】:
您应该将迁移视为数据库架构的版本控制系统。 makemigrations 负责将您的模型更改打包到单独的迁移文件中(类似于提交),而 migrate 负责将这些更改应用到您的数据库中。
每个应用程序的迁移文件位于该应用程序内的“迁移”目录中,并且旨在提交到其代码库并作为其代码库的一部分分发。您应该在您的开发机器上进行一次迁移,然后在您同事的机器、暂存机器以及最终的生产机器上运行相同的迁移。
黄金法则:开发一次,全部迁移
【讨论】:
简答
我建议在回购中排除迁移。代码合并后,只需运行./manage.py makemigrations就可以了。
长答案 我认为您不应该将迁移文件放入 repo。它会破坏其他人的开发环境和其他产品和阶段环境中的迁移状态。 (请参阅 Sugar Tang 的评论示例)。
在我看来,Django 迁移的目的是找到先前模型状态和新模型状态之间的差距,然后将差距序列化。如果代码合并后你的模型发生了变化,你可以简单地做makemigrations来找出差距。当您可以自动实现相同且无错误的迁移时,为什么还要手动小心地合并其他迁移? Django documentation 说,
它们*(迁移)*'被设计成大部分是自动的
;请保持这种状态。要手动合并迁移,您必须完全了解其他人已更改的内容以及更改的任何依赖关系。这是很多开销并且容易出错。所以跟踪模型文件就足够了。
这是一个关于工作流程的好话题。我愿意接受其他选择。
【讨论】:
manage.py makemigrations --merge 完全自动为我工作。