2010-11-06 6 views
20

J'ai un projet dans Git qui a plusieurs sous-modules, et j'ai besoin que ces sous-modules soient téléchargés et les fichiers disponibles pour utiliser le projet principal, et pour que les sous-modules fonctionnent, j'ai besoin de leur propre sous-modules à être disponibles etc. Donc, pour mettre en place ce que j'initialise récursivement les sous-modules en utilisant git submodule update --init --recursive.Sous-modules en double avec Git

Cependant, je l'ai remarqué que beaucoup de mes sous-modules ont des dépendances partagées, à la recherche quelque chose comme ça dans pseudocode (alpha -> beta représente que alpha a le sous-module beta)

my project -> submodule a -> submodule m 
      -> submodule b -> submodule m 
          -> submodule n -> submodule x 
      -> submodule c -> submodule x 

Ma question est: est-il possible d'éviter cette duplication en utilisant seulement git, tout en ayant (au moins une copie de) les fichiers pour chaque sous-module?

Je peux imaginer une solution avec des liens symboliques, mais il serait préférable que git gère cela pour moi, et je ne suis pas sûr que la mise en place des liens symboliques causerait des problèmes lors de la mise à jour des sous-modules.

Idéalement j'aimerais simplifier jusqu'à:

my project -> submodule a -> symlink(submodule m) 
      -> submodule b -> symlink(submodule m) 
          -> symlink(submodule n) 
      -> submodule c -> symlink(submodule x) 
      -> submodule m 
      -> submodule n -> symlink(submodule x) 
      -> submodule x 

Merci d'avance pour vos suggestions!

+0

Pas exactement la même question, mais extrêmement similaires: http://stackoverflow.com/questions/1419498/git-nested-submodules-and- dépendances – MarcH

Répondre

7

Ceci n'est pas intégré dans git, mais vous pouvez certainement le faire avec des liens symboliques comme vous le dites. Vous pouvez jeter un oeil à git new-workdir (du répertoire contrib git), qui fait essentiellement cela. Il n'est pas au courant de quoi que ce soit concernant les sous-modules, mais un sous-module ne sait pas qu'il s'agit d'un sous-module - c'est le dépôt parent qui connaît ce genre de choses. Je ne l'ai pas essayé, mais je suis assez certain que vous pouvez l'utiliser quelque chose comme ceci:

# remove the target first (new-workdir will refuse to overwrite) 
rm -rf submodule_b/submodule_m 

#    (original repo)   (symlinked repo) 
git new-workdir submodule_a/submodule_m submodule_b/submodule_m 

Il fonctionne par un lien symbolique quasi-totalité du répertoire .git; la chose notable qui n'est pas symétrique est HEAD; les deux répertoires peuvent avoir différentes choses extraites, mais partagent les mêmes références et objets.

De là, vous devriez être bon. Lorsque vous exécutez une commande git submodule dans le supermodule, elle entre dans les sous-modules et y exécute les commandes appropriées, ce qui fonctionne comme prévu. La seule chose dont vous avez besoin d'être conscient avec des dépôts symétriques comme ceci est qu'ils partagent le même ensemble de branches, donc si tous les deux ont la même branche empruntée, et que vous vous y engagez dans l'un, l'autre deviendra désynchronisé. Avec les sous-modules, cela ne pose généralement pas de problème, car ils sont essentiellement en état de tête détachée sauf si vous intervenez.

3

git-new-workdir pourrait ne pas être une bonne solution comme indiqué ici: http://comments.gmane.org/gmane.comp.version-control.git/196019

Il ne fonctionne pas pour moi, sous git 1.7.10.

Je l'ai résolu pour mon cas d'utilisation en utilisant des liens durs. Je cours OS X et le système de fichiers permet de créer des liens directs vers des répertoires: https://github.com/darwin/hlink

Maintenant, je peux relier les répertoires de sous-modules et les traiter de manière transparente. La liaison dure a également une belle propriété que tous les sous-modules sont entièrement reflétés, y compris HEAD qui est un comportement que je préfère dans mon cas.Ok, l'idée est d'avoir un repo sous-module "maître" et de lier dur toutes les copies "esclaves" à celui-ci. Cela les rendra tous indiscernables les uns des autres et entièrement synchronisés.

CAVEATS:

1) Cela fonctionne bien aussi longtemps que des chemins relatifs au travail .git. En d'autres termes, vous pouvez lier uniquement des sous-modules situés au même niveau de répertoire dans l'arborescence. C'était mon cas. Je suppose que vous pouvez facilement le réparer en modifiant les fichiers .gitfiles avec votre tâche de liaison. Note: Cela ne devrait pas être un problème avant git 1.7.10, car le .git de sous-module précédent était un répertoire autonome, pas simplement un fichier .git en clair pointant ailleurs.

2) Les liens durs peuvent introduire des incompatibilités. Par exemple TimeMachine est confus car il utilise des liens durs en interne pour le versionnage. Assurez-vous d'exclure votre formulaire de répertoire de projet TimeMachine.

Voici un exemple de ma tâche de rake faire le travail: https://github.com/binaryage/site/blob/3ef664693cafc972d05c57a64c41e89b1c947bfc/rakefile#L94-115