2009-09-14 9 views
43

Disons que je quatre projets nommés de base, A, B, super. L'arbre de dépendance est comme ceci:sous-modules imbriqués Git et dépendances

Super ---> Core 
     |-> A -> Core 
     |-> B -> Core 

Je veux chaque projet soit autonome, qui est, je veux être en mesure de départ et compiler chaque projet sur son propre (chacun avec ses dépendances bien sûr).

Je pensais à la cartographie de chaque projet à un référentiel, puis les dépendances se référant aux sous-modules, mais je vois les questions suivantes avec cette approche:

  1. Lors de la vérification super avec toutes ses dépendances, je finir avec trois copies de Core.
  2. Puisque les sous-modules sont complètement indépendants, chacune de ces trois copies pourrait pointer vers différentes révisions de Core et ce serait un désordre.

Alors ... Est-ce qu'il me manque quelque chose? Ai-je mal compris les sous-modules git ou les ai-je mal utilisés? Y a-t-il une autre solution à ce problème (autre que le recours aux dépendances binaires)?

Répondre

12

Vous venez de découvrir l'absence de dépendances outrepassée avec Git sous-modules:

Si super dépend de base, sa dépendance de base devrait « remplacer » les A et B ont avec Core.

La seule façon d'imiter ce serait de créer votre super projet, la façon dont vous avez fait,
et pour supprimer le sous-module de base A et B.
(ce qui signifie super dépend maintenant de A » et B ', A' étant A sans noyau, B 'étant B sans noyau)

7

Les dépôts git doivent être assez atomiques dans la mesure où chaque référentiel est une entité autonome dans un but spécifique. Quel est le but du super projet autre que de combiner les projets A et B? S'il n'y a rien d'unique (c'est-à-dire des fichiers qui ne sont pas dans A, B ou Core) alors c'est assez redondant. EDIT: Parce que les sous-modules git sont particulièrement douloureux à un endroit où j'ai travaillé, nous avons mis en place notre propre système de dépendance qui suit les dépôts dépendants via des fichiers texte. Nous l'avons mis en place afin de toujours suivre la tête d'une branche, pas un commit particulier.

Nous avons pu mettre en place tous nos projets comme si elles font partie du projet Super comme celui-ci:

Super 
|-A 
|-B 
|-Core 

Les projets de référence les uns des autres en utilisant des chemins relatifs par exemple . Contrôle un repo ne fonctionne pas, vous devez créer un autre repo « super » pour travailler seulement sur A:

AWorking 
|-A 
|-Core 

EDIT Une autre raison de ce comportement dans git est qu'il ne peut pas suivre les choses que sont au-dessus du répertoire repo racine (c'est-à-dire au dessus du dossier contenant le dossier .git), ce qui serait certainement nécessaire si vous voulez que vos super-projets et sous-projets se réfèrent aux mêmes dépôts.

+0

Super est un projet en soi. Ne supposez pas qu'il n'a pas de contenu juste parce que je l'ai appelé Super. –

+1

Mais je veux que chaque projet soit autonome. Et j'aime que les sous-modules git soient fixés à un commit particulier au lieu de suivre comme svn externals, de sorte qu'un changement de Core ne rompe pas immédiatement A, B et Super. –

+1

Que vous suiviez des branches ou que vous commettiez des SHA, c'est à vous de décider. Mais la meilleure réponse à votre problème est qu'il n'est pas vraiment possible d'avoir à la fois l'option autonome et l'option super-projet. En pratique, j'ai trouvé qu'un super-projet pour chaque sous-projet n'est pas si important. –

0

Je ne tenterais pas de mapper une arborescence de dépendances avec des sous-modules - pour les raisons que vous avez déjà découvertes.

Les sous-modules suivent une révision donnée d'une branche donnée, ils sont donc utiles pour donner un instantané d'un ensemble cohérent de modules. Par conséquent, si votre projet nécessitait le suivi d'un certain ensemble de versions de différents modules en une seule unité, vous pouvez les regrouper en tant que sous-modules.Vous pouvez ensuite marquer différents ensembles de modules à des versions différentes, pour donner un historique du projet, où chaque étiquette montre quelles versions de quels modules étaient compatibles à un moment donné.

tags/ 
    release1/ 
      |-> [email protected] 
      |-> [email protected] 
      |-> [email protected] 
    release2/ 
      |-> [email protected] 
      |-> [email protected] 
      |-> [email protected] 

au moins que la façon dont je les comprends, bien que, comme la plupart des choses avec Git, il y a probablement beaucoup plus que ça. En termes de gestion des dépendances, tout ce que je peux dire c'est trouver une autre façon, ce n'est pas ce que Git avec ou sans sous-modules a été conçu comme je le comprends.

+0

Ok ... mais je pense que cela résout un problème différent ... pas celui dont je parle. –

6

Je pense que le problème ici est une discordance entre la conception de Git et le problème que vous cherchez à résoudre.

Git est bon pour le suivi des arbres. Les relations de dépendance entre les projets peuvent (et probablement le font) former un graphique. Un arbre est un graphique mais un graphique n'est pas nécessairement un arbre. Puisque votre problème est de savoir comment représenter efficacement un graphique, un arbre n'est pas le meilleur outil pour le travail.

est ici une approche qui pourrait fonctionner:

Un projet git a un répertoire .gitmodules où il enregistre « indices » indiquant quels projets une livraison peut dépendre, où ils se trouvent, et quel chemin à l'intérieur du projet ils devraient être insérés à. (http://osdir.com/ml/git/2009-04/msg00746.html)

Vous pouvez ajouter un script qui lit ces informations à partir d'un ensemble de projets, mappe les indications trouvées dans le fichier .gitmodules de chaque projet vers les emplacements du système de fichiers où ces projets ont été placés, puis ajoute des symboles liens à partir des chemins où git s'attend à vérifier les sous-modules aux emplacements réels du système de fichiers des projets respectifs.

Cette approche utilise des liens symboliques pour sortir du moule Arbre et créer un graphique. Si nous enregistrons les liens directement dans les repos git, nous aurons des chemins relatifs spécifiques à notre configuration locale enregistrés dans les projets individuels, et les projets ne seront pas 'complètement indépendants' comme vous le vouliez. Par conséquent, le script pour construire dynamiquement les liens symboliques.

Je pense que cette approche pourrait interférer avec git de manière indésirable, puisque nous avons pris des chemins où elle s'attend à trouver une chose, et y mettre quelque chose d'autre à la place. Peut-être que nous pourrions .gitignore les chemins de lien symbolique. Mais maintenant nous écrivons ces chemins deux fois et violons DRY. À ce stade, nous sommes également très loin de faire semblant d'utiliser des sous-modules. Nous pourrions enregistrer les dépendances ailleurs dans chaque projet, et laisser le fichier .gitmodules pour les choses attendues par git. Nous allons donc créer notre propre fichier, disons, .dependencies, et chaque projet peut y indiquer ses dépendances. Notre script va regarder là-bas, puis va construire ses liens symboliques.

Hmm, je pense que je viens de décrire un système de gestion package ad-hoc, avec son propre format de package léger :) suggestion de

megamic semble être une bonne utilisation des sous-modules git pour moi.Nous ne traitons ici que du tracé d'un ensemble plutôt que d'un graphique, et un ensemble se glisse facilement dans un arbre. Un arbre profond d'un niveau est essentiellement un nœud parent et un ensemble de nœuds enfants.

Comme vous l'avez souligné, cela ne résout pas complètement le problème énoncé dans votre question. Nous pouvons distinguer deux types distincts d'informations «cela marche avec ça» qui nous intéressent: 1. Une déclaration d'une version d'un projet (vraisemblablement par l'auteur du projet) disant «J'ai besoin de la version X du projet Y» 2. Une déclaration utilisée par votre propre configuration de construction indiquant "J'ai testé avec succès notre système en utilisant cet ensemble de versions de projet"

réponse de megamic résolue (2) mais pour (1) nous voulons toujours que les projets nous disent quelles sont leurs dépendances. Ensuite, nous pouvons utiliser l'info de (1) pour calculer ces ensembles de versions que nous finirons par enregistrer comme (2). Pour autant que je sache, la plupart des bons outils de gestion de paquets sont conçus pour les utilisateurs d'une langue ou d'un système d'exploitation spécifiques.

. Voir Bundler pour les paquets 'gem' dans le monde de ruby ​​et apt pour les paquets '.deb' dans le monde Debian.

Si quelqu'un connaît une bonne solution neutre pour le système d'exploitation, neutre pour le langage, qui convient bien aux projets de programmation 'polyglotte' (http://blog.heroku.com/archives/2011/8/3/polyglot_platform/), je serais très intéressé! Je devrais afficher cela comme une question.

+1

+1 Comme votre problème est de savoir comment représenter efficacement un graphique, un arbre n'est pas le meilleur outil pour le travail. –

2

Je pense que vous pouvez gérer la cohérence comme ceci: définir une branche "référence" ou une série d'étiquettes avec le même nom dans toutes vos bibliothèques "Core" (note: il n'y a qu'une seule bibliothèque "Core" dans votre Exemple). Ensuite, demandez aux développeurs de sous-projets (A, B, ...) de passer régulièrement à la version de référence de "Core" dès qu'ils le peuvent. Avant d'exécuter une build, vérifiez que "Core (s)" est utilisé de manière cohérente sur A, B, C, ... en exécutant ces trois commandes dans un checkout "Super", propre et récursif. :

# 1. Switch to the reference version (= "Force" consistency where need be) 
git submodule foreach --recursive 'git checkout [origin/]reference || true' 

# 2a. Show which inconsistencies you just forced; terse output 
git status -s; git submodule foreach --recursive git status -s 2>/dev/null 

# 2b. Same but verbose output 
git submodule; git submodule foreach --recursive git submodule 

# 3. Switch back to versions individually defined by sub-projects 
git submodule update --recursive 

la commande "sortie Terse" 2a ci-dessus met en évidence que sous-projet (s) ne sont pas en utilisant la version de "référence" du noyau.

Vous pouvez facilement étendre l'approche pour afficher les différences, forcer les mises à niveau ou faire tout autre chose que vous aimez.

2

Une petite tâche utilitaire transformant des sous-modules partagés en clones à l'aide de liens physiques peut fonctionner.

Vous pouvez lire ma solution complète ici: https://stackoverflow.com/a/10265084/84283