Dois-je ajouter les fichiers de migration Django dans le fichier .gitignore?

130

Dois-je ajouter les fichiers de migration Django dans le .gitignorefichier?

J'ai récemment eu beaucoup de problèmes git en raison de conflits de migration et je me demandais si je devrais marquer les fichiers de migration comme ignorés.

Si tel est le cas, comment pourrais-je ajouter toutes les migrations que j'ai dans mes applications et les ajouter au .gitignorefichier?

Michael Smith
la source

Réponses:

138

Citant la documentation sur les migrations Django :

Les fichiers de migration de chaque application se trouvent dans un répertoire de «migrations» à l'intérieur de cette application et sont conçus pour être validés et distribués dans le cadre de sa base de code. Vous devriez les faire une fois sur votre machine de développement, puis exécuter les mêmes migrations sur les machines de vos collègues, vos machines de préparation et éventuellement vos machines de production.

Si vous suivez ce processus, vous ne devriez pas avoir de conflits de fusion dans les fichiers de migration.

Lors de la fusion de branches de contrôle de version, vous pouvez toujours rencontrer une situation dans laquelle vous avez plusieurs migrations basées sur la même migration parent, par exemple si à différents développeurs ont introduit une migration simultanément. Une façon de résoudre cette situation est d'introduire une _merge_migration_. Cela peut souvent être fait automatiquement avec la commande

./manage.py makemigrations --merge

qui introduira une nouvelle migration qui dépend de toutes les migrations de tête actuelles. Bien sûr, cela ne fonctionne que lorsqu'il n'y a pas de conflit entre les migrations principales, auquel cas vous devrez résoudre le problème manuellement.


Étant donné que certaines personnes ici ont suggéré de ne pas valider vos migrations vers le contrôle de version, j'aimerais développer les raisons pour lesquelles vous devriez réellement le faire.

Tout d'abord, vous avez besoin d'un enregistrement des migrations appliquées à vos systèmes de production. Si vous déployez des modifications en production et souhaitez migrer la base de données, vous avez besoin d'une description de l'état actuel. Vous pouvez créer une sauvegarde distincte des migrations appliquées à chaque base de données de production, mais cela semble inutilement fastidieux.

Deuxièmement, les migrations contiennent souvent du code manuscrit personnalisé. Il n'est pas toujours possible de les générer automatiquement avec ./manage.py makemigrations.

Troisièmement, les migrations doivent être incluses dans la révision du code. Ce sont des changements importants dans votre système de production, et il y a beaucoup de choses qui peuvent mal tourner avec eux.

Bref, si vous vous souciez de vos données de production, veuillez vérifier vos migrations vers le contrôle de version.

Sven Marnach
la source
24
Nous, une équipe de développeurs, avons exactement le même problème aussi. Si un membre joue makemigrations some_app, non seulement les modèles sous le contrôle de ce membre seront affectés, mais également d'autres modèles associés seront également affectés. Autrement dit, les fichiers de migration (00 * _ *) dans d'autres applications seront modifiés. Et cela provoque de nombreux problèmes de conflit lors de la poussée ou de l'extraction de GitHub. Comme actuellement notre système n'est pas prêt pour la production, nous n'avons que .gitignorele fichier de migration. Nous ne savons toujours pas comment le résoudre lorsque le système entre en production. Quelqu'un a-t-il des solutions?
Randy Tang
2
Donc, si je comprends bien, vous devez extraire les migrations de votre projet. Lorsque vous changez quelque chose, vous devez effectuer des migrations locales. Poussez-le à nouveau et le buildserver effectuera la migration? (Très important bien sûr, tout le monde a les bonnes versions)
lvthillo
nous n'utilisons jamais de migrations django. tout le monde se connecte à une base de données de test centrale, si une modification est nécessaire, elle est effectuée manuellement au niveau de la base de données si nécessaire. Cette méthode fonctionne bien si le système est suffisamment mature alors qu'il n'aura pas besoin de nombreuses mises à jour de schéma de base de données.
gurel_kaynak
@ yltang52 Nous essayons actuellement de le comprendre également, pouvez-vous partager des idées? Je pense qu'une fois que vous passez à la production, vous n'avez pas d'autre choix que de maintenir ces migrations pour permettre des correctifs plus faciles et un contrôle de version globalement plus facile. Je me demande également ce que vous faites avec les données d'état initial (comme les paramètres stockés dans db). Comment les entretenez-vous?
Daniel Dubovski
3
Je ne pense pas que vous devriez mettre les fichiers de migration dans le référentiel. Cela gâchera les états de migration dans l'environnement de développement d'autres personnes et dans d'autres environnements de production et de scène. (reportez-vous au commentaire de Sugar Tang pour des exemples). Le fichier des modèles de suivi est suffisant.
Diansheng
19

Vous pouvez suivre le processus ci-dessous.

Vous pouvez exécuter makemigrationslocalement et cela crée le fichier de migration. Validez ce nouveau fichier de migration dans le dépôt.

À mon avis, vous ne devriez pas du tout tourner makemigrationsen production. Vous pouvez exécuter migrateen production et vous verrez que les migrations sont appliquées à partir du fichier de migration que vous avez validé à partir de local. De cette façon, vous pouvez éviter tous les conflits.

EN LOCAL ENV , pour créer les fichiers de migration,

python manage.py makemigrations 
python manage.py migrate

Maintenant, validez ces fichiers nouvellement créés, quelque chose comme ci-dessous.

git add app/migrations/...
git commit -m 'add migration files' app/migrations/...

DANS PRODUCTION ENV , exécutez uniquement la commande ci-dessous.

python manage.py migrate
SuperNova
la source
3
À mon avis, le fichier de migration ne devrait faire partie du dépôt qu'une fois l'application déployée. Cela comptait comme des migrations initiales. Si l'application est toujours en développement, nous pouvons l'ignorer en toute sécurité. Mais une fois qu'il est mis en ligne. C'est tout! C'est le signe que les migrations doivent être mises en dépôt. Tous les autres membres doivent ensuite suivre ces migrations et mettre les leurs si nécessaire
swdev
1
Très bon point à exécuter uniquement migrateet JAMAIS makemigrationspour les migrations validées. Jamais pensé à ça.
polariser
9

Citation de la documentation 2018, Django 2.0. (deux commandes séparées = makemigrationset migrate)

La raison pour laquelle il existe des commandes distinctes pour effectuer et appliquer des migrations est que vous allez valider les migrations vers votre système de contrôle de version et les expédier avec votre application; ils facilitent non seulement votre développement, mais ils sont également utilisables par d'autres développeurs et en production.

https://docs.djangoproject.com/en/2.0/intro/tutorial02/

techkuz
la source
7

TL; DR: validez les migrations, résolvez les conflits de migration, ajustez votre workflow git.

Il semble que vous deviez ajuster votre flux de travail git , au lieu d'ignorer les conflits.

Idéalement, chaque nouvelle fonctionnalité est développée dans une branche différente et fusionnée avec une pull request .

Les PR ne peuvent pas être fusionnés en cas de conflit. Par conséquent, celui qui doit fusionner sa fonctionnalité doit résoudre le conflit, migrations incluses. Cela peut nécessiter une coordination entre différentes équipes.

Il est cependant important de valider les fichiers de migration! En cas de conflit, Django pourrait même vous aider à résoudre ces conflits ;)

Sdra
la source
C'est la bonne réponse. Un flux de travail du système de versionnage opérationnel semble être implicite dans la documentation de django mais c'est fondamental.
Eric
3

Je ne peux pas imaginer pourquoi vous auriez des conflits, à moins que vous ne modifiiez les migrations d'une manière ou d'une autre? Cela se termine généralement mal - si quelqu'un manque des validations intermédiaires, il ne sera pas mis à niveau à partir de la version correcte et sa copie de la base de données sera corrompue.

Le processus que je suis est assez simple - chaque fois que vous changez les modèles pour une application, vous engagez également une migration, puis cette migration ne change pas - si vous avez besoin de quelque chose de différent dans le modèle, alors vous changez le modèle et commettez un nouvelle migration à côté de vos changements.

Dans les projets greenfield, vous pouvez souvent supprimer les migrations et recommencer à zéro avec une migration 0001_ lors de la publication, mais si vous avez du code de production, vous ne pouvez pas (bien que vous puissiez réduire les migrations en une seule).

Anthony Briggs
la source
Bon point de repartir de zéro avec 0001 pour la sortie.
andho
3

La solution généralement utilisée est que, avant que quoi que ce soit ne soit fusionné dans master, le développeur doit retirer toutes les modifications à distance. S'il y a un conflit dans les versions de migration, il doit renommer sa migration locale (celle distante a été exécutée par d'autres développeurs, et, potentiellement, en production), en N + 1.

Pendant le développement, il peut être acceptable de ne pas valider les migrations (n'ajoutez pas d'ignorer, mais ne les faites pas add). Mais une fois que vous êtes entré en production, vous en aurez besoin pour garder le schéma synchronisé avec les changements de modèle.

Vous devez ensuite modifier le fichier et changer dependenciesla dernière version distante.

Cela fonctionne pour les migrations Django, ainsi que pour d'autres applications similaires (sqlalchemy + alembic, RoR, etc.).

WhyNotHugo
la source
1

Avoir un tas de fichiers de migration dans git est compliqué. Il n'y a qu'un seul fichier dans le dossier de migration que vous ne devez pas ignorer. Ce fichier est un fichier init .py, si vous l'ignorez, python ne cherchera plus de sous-modules dans le répertoire, donc toute tentative d'importation des modules échouera. La question devrait donc être de savoir comment ignorer tous les fichiers de migration mais init .py? La solution est: Ajoutez '0 * .py' aux fichiers .gitignore et cela fait parfaitement le travail.

J'espère que cela aide quelqu'un.

Gizachew Soboksa
la source
1

Gitignorez les migrations, si vous avez des bases de données distinctes pour l'environnement de développement, de préparation et de production. Pour dev. buts Vous pouvez utiliser la base de données sqlite locale et jouer avec les migrations localement. Je vous recommande de créer quatre branches supplémentaires:

  1. Master - Nettoyez le code frais sans migrations. Personne n'est connecté à cette branche. Utilisé pour les révisions de code uniquement

  2. Développement - développement quotidien. Pousser / tirer accepté. Chaque développeur travaille sur sqlite DB

  3. Cloud_DEV_env - environnement DEV cloud / serveur distant. Tirez uniquement. Conserver les migrations localement sur la machine, qui est utilisée pour le déploiement de code et les migrations à distance de la base de données Dev

  4. Cloud_STAG_env - environnement STAG cloud / serveur distant. Tirez uniquement. Conserver les migrations localement sur la machine, qui est utilisée pour le déploiement de code et les migrations à distance de la base de données Stag

  5. Cloud_PROD_env - environnement DEV cloud / serveur distant. Tirez uniquement. Conserver les migrations localement sur la machine, qui est utilisée pour le déploiement de code et les migrations à distance de la base de données Prod

Remarques: 2, 3, 4 - les migrations peuvent être conservées dans des dépôts mais il devrait y avoir des règles strictes de fusion des pull requests, nous avons donc décidé de trouver une personne, responsable des déploiements, donc le seul à avoir tous les fichiers de migration - notre déploiement -er. Il conserve les migrations de bases de données distantes chaque fois que nous avons des modifications dans les modèles.

Yevhen Dyachenko
la source
-3

Réponse courte Je propose d'exclure les migrations dans le repo. Après la fusion de code, exécutez simplement ./manage.py makemigrationset vous êtes prêt.

Réponse longue Je ne pense pas que vous devriez mettre les fichiers de migration dans le dépôt. Cela gâchera les états de migration dans l'environnement de développement d'autres personnes et dans d'autres environnements de production et de scène. (reportez-vous au commentaire de Sugar Tang pour des exemples).

De mon point de vue, le but des migrations Django est de trouver des écarts entre les états de modèle précédents et les nouveaux états de modèle, puis de sérialiser l'écart. Si votre modèle change après la fusion du code, vous pouvez simplement le faire makemigrationspour trouver l'écart. Pourquoi voulez-vous fusionner manuellement et soigneusement d'autres migrations alors que vous pouvez réaliser la même chose automatiquement et sans bogue? La documentation de Django dit,

Ils * (migrations) * sont conçus pour être principalement automatiques

; s'il vous plaît, gardez-le de cette façon. Pour fusionner les migrations manuellement, vous devez bien comprendre ce que les autres ont changé et toute dépendance des modifications. C'est beaucoup de frais généraux et sujets aux erreurs. Le fichier des modèles de suivi est donc suffisant.

C'est un bon sujet sur le flux de travail. Je suis ouvert à d'autres options.

Diansheng
la source
4
Cela ne fonctionnera que pour les projets de jouets et présente de nombreux inconvénients. Il cesse immédiatement de fonctionner pour les migrations manuscrites, pour les services utilisant plusieurs serveurs d'applications éphémères (c'est-à-dire toute application sérieuse) et pour les applications composées de nombreuses applications Django chacune avec leurs propres migrations. Et je ne comprends pas ce à quoi vous faites référence avec "la fusion manuelle des migrations" - manage.py makemigrations --mergefonctionne de manière entièrement automatique pour moi.
Sven Marnach
@Sven Marnach, je travaillais en effet sur des applications petites mais sérieuses. Et ça fonctionne pour moi.
Diansheng le