Dans un git
environnement où nous avons modularisé la plupart des projets, nous sommes confrontés à un projet par référentiel ou à plusieurs projets par problème de conception de référentiel . Considérons un projet modularisé:
myProject/
+-- gui
+-- core
+-- api
+-- implA
+-- implB
Aujourd'hui, nous avons un projet par référentiel . Cela donne la liberté de
release
composants individuelstag
composants individuels
Mais les branch
composants sont également encombrants , car la ramification api
nécessite souvent des branches équivalentes dans core
, voire d'autres composants.
Étant donné que nous voulons release
des composants individuels, pouvons-nous obtenir la même flexibilité en utilisant plusieurs projets par conception de référentiel .
Quelles sont les expériences existantes et comment / pourquoi avez-vous abordé ces problèmes?
java
programming-practices
version-control
git
maven
Johan Sjöberg
la source
la source
git-describe
.Réponses:
one project per repository
La façon dont vous l'avez décrite ci-dessus présente trois inconvénients majeurs . Celles-ci sont moins vraies s’il s’agit de projets véritablement distincts, mais les changements qui en résonnent nécessitent souvent d’être modifiés, ce qui peut réellement exagérer ces problèmes:git bisect
deviennent beaucoup plus difficiles à utiliser lorsque vous répartissez votre référentiel en sous-référentiels. C'est possible, ce n'est tout simplement pas aussi facile, ce qui signifie que la recherche de bogues en temps de crise est d'autant plus difficile.git log
que, tout simplement, ne produisent pas l’historique de manière aussi significative avec des structures de référentiel fracturées. Vous pouvez obtenir des résultats utiles avec des sous - modules ou des sous-arbres, ou via d'autres méthodes scriptables, mais ce n'est pas la même chose que de tapertig --grep=<caseID>
ou d'git log --grep=<caseID>
analyser tous les commits qui vous intéressent. Votre histoire devient plus difficile à comprendre, ce qui la rend moins utile lorsque vous en avez vraiment besoin.En fin de compte, c'est un calcul du coût d'opportunité. Chez un ancien employeur, notre application principale était divisée en 35 sous-répertoires différents. De plus, nous avons utilisé un ensemble compliqué de scripts pour effectuer une recherche dans l'historique, nous assurer que l'état (c'est-à-dire la production par rapport aux branches de développement) était identique, et les déployer individuellement ou en masse.
C'était trop; trop pour nous au moins. Les frais généraux de gestion ont rendu nos fonctionnalités moins souples, rendu les déploiements beaucoup plus difficiles, obligé à enseigner trop longtemps aux nouveaux développeurs et, à la fin, nous pouvions à peine nous souvenir de la raison pour laquelle nous avions divisé le référentiel. Un beau jour de printemps, j'ai dépensé 10 dollars pour un après-midi de calcul en cluster dans EC2. J'ai réparé les pensions avec une douzaine d'
git filter-branch
appels. Nous n'avons jamais regardé en arrière.la source
Christopher a très bien énuméré les inconvénients d'un modèle à un projet par dépôt. J'aimerais discuter de certaines des raisons pour lesquelles vous pourriez envisager une approche à référentiel multiple. Dans de nombreux environnements dans lesquels j'ai travaillé, une approche multi-référentiels constituait une solution raisonnable, mais il n’était pas toujours facile de décider du nombre de référentiels à disposer et du lieu où opérer les réductions.
Dans mon poste actuel, j'ai migré un énorme dépôt CVS avec un dépôt unique avec plus de dix ans d’histoire dans un certain nombre de dépôts git. Depuis cette décision initiale, le nombre de référentiels a augmenté (grâce aux actions d'autres équipes), au point que je soupçonne que nous en avons plus que ce qui serait optimal. Certains nouveaux employés ont suggéré de fusionner les référentiels, mais j’ai plaidé contre. Le projet Wayland a une expérience similaire. Dans une conversation que j'ai récemment vue, ils avaient, à un moment donné, plus de 200 dépôts git, pour lesquels le responsable s'est excusé. En regardant leur site Web , je vois maintenant qu'ils sont à 5 heures, ce qui semble raisonnable. Il est important de noter que la jonction et la division de référentiels est une tâche gérable, et qu'il est acceptable d'expérimenter (dans des limites raisonnables).
Alors, quand voulez-vous plusieurs référentiels?
Les points 2 et 3 ne sont significatifs que si le point 1 tient. En scindant nos référentiels, j'ai considérablement réduit les délais de nos collègues hors site, réduit la consommation de disques et amélioré le trafic réseau.
4 et 5 sont plus subtiles. Lorsque vous séparez les dépôts d'un client et d'un serveur, cela rend plus onéreuse la coordination des modifications entre le code client et le code serveur. Cela peut être positif car cela encourage une interface découplée entre les deux.
Même avec les inconvénients des projets multi-référentiels, de nombreux travaux respectables sont effectués de cette manière - on pense à Wayland et à boost. Je ne crois pas qu'un consensus sur les meilleures pratiques ait encore évolué et qu'il faut faire preuve de jugement. Des outils permettant de travailler avec plusieurs référentiels (git-sous-arbre, git-sous-module et autres) sont encore en cours de développement et d'expérimentation. Mon conseil est d'expérimenter et d'être pragmatique.
la source
Comme nous utilisons GitHub, nous avons en réalité plusieurs projets dans un même dépôt, mais nous nous assurons que ces projets / modules sont correctement modularisés (nous utilisons les conventions -api et -core + Maven +, ainsi que les vérifications statiques et d'exécution et pouvons même aller à OSGi un jour pour démarrer). .
Qu'est-ce que cela économise? Nous n’avons pas à émettre plusieurs demandes d’extraction si nous modifions quelque chose de petit dans plusieurs projets. Les problèmes et le wiki sont centralisés, etc.
Nous traitons toujours chaque module / projet comme un projet indépendant approprié et les construisons et les intégrons séparément dans notre serveur CI, etc.
la source
submodules
ou libérez-vous / étiquetez-vous le référentiel entier?git log -1 -- <project_dir>
). C'est vraiment génial. Cette réponse mérite plus de votes positifs.Pour moi, la principale différence en utilisant un ou plusieurs référentiels réside dans les réponses aux questions suivantes:
À titre d’exemple, j’ai une petite application (client seulement) qui vérifie la "qualité" d’un référentiel Subversion. Il y a l'implémentation principale, qui pourrait être lancée à partir de la ligne de commande et fonctionne bien avec Java 6. Mais j'ai commencé à implémenter une interface utilisateur, qui utilise JavaFX dans le cadre de Java 8. J'ai donc divisé le 2, et créé un second référentiel (avec un second processus de compilation), avec un planning différent, ...
J'aime les réponses ci-dessus (votées), mais je pense qu'elles ne sont pas toute l'histoire vraie. Je voulais donc ajouter les arguments en faveur du fractionnement des référentiels. Donc, la vraie réponse (quand diviser) peut être quelque part au milieu ...
la source
Il se pourrait que -sous - arbre git (voir le blog Atlassian , blog de moyen ou lien du noyau ) serait un bon moyen pour que vous avez. Ainsi, chacun de vos projets de niveau supérieur utilisera un ensemble de sous-arborescence avec éventuellement différentes versions.
la source
D'après votre exemple, les référentiels devraient être configurés en fonction de leur interdépendance. Tous les raisonnements sur la conception de MicroServices et de la conception par domaine s'appliquent ici: dans certains cas, le code en double est acceptable, travaillez avec des interfaces, ne coupez pas la compatibilité à moins que vous n'ayez vraiment à le faire, etc.
À mon avis, une interface utilisateur devrait être indépendante du backend. Ainsi, un référentiel de projet d'interface utilisateur doit généralement contenir le code d'interface utilisateur et le contrôleur de client. Le contrôleur client se connecte aux contrôleurs de service de manière abstraite. Ils utiliseront une abstraction client / API de service qui est versionnée séparément du service, de sorte qu'un service puisse être mis à jour sans rompre le ou les clients (il peut y avoir plusieurs clients différents).
Ainsi, un service lui-même devrait être son propre référentiel. À mon avis, le service n’est qu’une empaquetage d’une logique de gestion basée sur un seul point de vérité. La logique métier doit donc généralement être distincte de la technologie de service qui l'héberge. D'autre part, la mise en œuvre du référentiel est généralement si étroitement liée à la logique métier qu'elle pourrait être intégrée dans le même référentiel. Mais même là, votre kilométrage peut varier.
Bien sûr, les projets simples qui ne risquent pas de changer beaucoup en termes de technologie ou de prise en charge de plusieurs piles, où toutes les interfaces utilisateur peuvent être hébergées à partir de la même source que le serveur principal et les services principaux étant généralement utilisés uniquement par le même client, peuvent en bénéficier davantage. référentiels étroitement intégrés.
Dans ce cas, il vous suffirait probablement de disposer de la totalité de la verticale dans un référentiel et de vous assurer que vos domaines fonctionnels sont correctement autonomes dans leur propre référentiel. Vous disposez alors toujours de la plupart des avantages des référentiels plus petits et des frais généraux minimes dans le cas contraire.
la source