J'ai deux projets ou plus (appelons-les ProjectFoo et ProjectBar ) ayant un code commun que j'ai mis dans un sous-module.
Ma compréhension est que si je valide des modifications d'un sous-module de l'intérieur ProjectFoo ce sera dans une tête détachée que seuls tous Les clones ProjectFoo peuvent voir:
(master) $ cd ProjectFooBarCommoneSubmodule/
(master) $ git commit -am "Common code fix."
(56f21fb0...) $ git Push
Everything up-to-date
C'est probablement parce que la branche master
n'a pas changé. Je pourrais probablement faire quelque chose comme git checkout master && git merge Everything up-to-date
mais cela semble assez moche. Peut-être un git reset --hard master
ferait de même mais cela semble encore plus laid.
Comment avoir un code commun partagé par projet, mis à jour de l'intérieur les projets l'utilisant? En d'autres termes, la validation de ce sous-module doit mettre à jour tous les différents référentiels ( référentiels, pas seulement les clones ) qui utilisent ce même sous-module.
---- ÉDITER ----
Visiblement, mon référentiel extrait a été foiré et cassé. Cela aurait dû fonctionner dès le début comme ça (sur ProjectFoo dans cet exemple):
(master) $ cd ProjectFooBarCommoneSubmodule/
(master) $ git commit -am "Common code fix."
(master) $ git Push
....
fbfdd71..0acce63 master -> master
(master) $ cd ..
(master) $ git add ProjectFooBarCommoneSubmodule
(master) $ git commit -m "Submodule update."
Ensuite, pour obtenir ce changement à partir d'autres projets, comme ProjectBar :
(master) $ cd ProjectFooBarCommoneSubmodule/
(master) $ git pull
Mettre à jour vers le dernier code commun. UNE git checkout master
peut être requis s'il est sur une tête détachée.
Réponse courte:
cd ProjectFooBarCommoneSubmodule
git checkout master
<Do your editing>
git commit --all -m "Lots of fixes"
git Push submodule_Origin master
cd ..
git add ProjectFooBarCommoneSubmodule
git commit -m "Bumped up the revision of ProjectFooBarCommoneSubmodule"
git Push Origin master
Le plus long:
Les sous-modules Git sont un mécanisme de dépendance, où le projet principal (disons A) définit une révision spécifiée dans un sous-projet (disons B), qui sera utilisée dans la construction du projet A. Pour que l'outil soit utile, le comportement doit être prévisible du point de vue de A: s. Les dépendances ne peuvent pas changer, sauf si quelqu'un décide d'incorporer la modification au projet A. Toutes sortes de choses désagréables pourraient se produire, si les modifications du projet B: s étaient automatiquement importées, dont les erreurs de compilation sont probablement les meilleures, car A remarquerait immédiatement les échecs. C'est pourquoi la tête de B: s est maintenue à l'état détaché.
L'état de B est stocké dans A (consultez git submodule status
), et un changement de révision doit être effectué et validé en A, pour qu'il ait un effet. C'est ce qui se passe dans l'exemple ci-dessus, A modifie le numéro de révision stocké dans le référentiel et augmente la version à la dernière. Le processus devra également être répété dans l'autre référentiel principal, donc pas de commutateur automatique "use master" AFAIK.
BTW. Les chapitre du livre Git sur les sous-modules et les page de manuel des sous-modules contiennent de nombreuses informations utiles sur les sous-modules, comme l'utilisation normale et les pièges typiques. Vaut le détour.
EDIT: je vais essayer de mieux expliquer cela
J'ai pris la liberté de créer des exemples de projets sur mon compte github . Les commits sont vides de sens et contiennent du courrier indésirable, mais la configuration devrait être correcte. Veuillez le vérifier pour suivre.
ProjectFoo et ProjectBar partagent le code dans le sous-module commun.
ProjectFooBarCommoneSubmodule: master is 6850e4e4c1fac49de398
Dans ProjectFoo:
git submodule status
-6850e4e4c1fac49de39890703f21486ca04b87a0 commun
Dans ProjectBar:
git submodule status
-6850e4e4c1fac49de39890703f21486ca04b87a0 commun
Donc, les deux pointent vers la même révision, non? L'astuce consiste à voir que ProjectFoo et ProjectBar pointent vers la révision (6850e4e4c1fac49de39890703f21486ca04b87a0) pas la branche (master), bien que ce soit la même chose. Le premier est une tête détachée et l'autre une branche nommée.
Si vous voulez faire quelques corrections sur ProjectFooBarCommoneSubmodule, vous pouvez aller dans le sous-répertoire dans par ex. ProjectFoo et choisissez la branche au lieu de la révision :
git checkout master
<Do your coding and pushing here>
Ensuite, remontez d'un répertoire et vérifiez l'état du sous-module git. Il devrait vous dire que vous n'êtes plus synchronisé. Par exemple
git submodule status
+ e24bd2bf45d52171a63b67ac05cd4be0ac965f60 commun (têtes/master-1-ge24bd2b)
Vous pouvez maintenant faire un ajout git, pour définir la référence à ce commit particulier (ge24bd ...), faire un commit, et après cela, la référence du sous-module pointe vers cette révision, qui se trouve également être maître sur ProjectFooBarCommoneSubmodule.
Maintenant, vous devez également mettre à jour la référence dans ProjectBar. Allez dans ProjectBar/common, et faites git fetch Origin (c'est une fusion rapide), faites
git checkout master
cd ..
git add common
git commit -m "Bumped up the revision"
git Push Origin master # to publish the revision bump to everybody else
Ainsi, comme avec tout référentiel git, vous n'avez pas besoin de travailler sur une tête détachée. Vous pouvez soit travailler sur maître, soit créer une branche nommée. Dans les deux cas, assurez-vous que l'amont contient les modifications de ProjectFooBarCommoneSubmodule, sinon vous casserez ProjectFoo et ProjectBar, s'ils font référence à quelque chose qui n'existe pas. J'espère que cela l'a mieux expliqué
Sur le submodule
: git Push Origin HEAD:master
Remarquer:
git submodule foreach 'git commit -a'
échouera si l'un des sous-modules ne contient aucun engagement à faire.
Pour vous en débarrasser, vous devez forcer le résultat de la commande à 0.
git submodule foreach "git commit -am 'your comment' || echo ' '"
En utilisant l'écho canalisé, vous forcez la commande entière à revenir avec 0 et continuez à exécuter la commande commit sur les autres sous-modules
Je fais juste:
git submodule foreach git Push -u Origin master
Si vous souhaitez valider et pousser tous les sous-modules à la fois, procédez comme suit:
git submodule foreach 'git commit -a' ;
git submodule foreach 'git Push --all' ;
git commit -a && \
git Push --all --recurse-submodules=on-demand
Pour fusionner changé de détaché HEAD dans master, exécutez:
git rebase HEAD master
puis checkout master (utilisez -f
pour force):
git checkout master
Si vous avez plusieurs sous-modules à gérer, utilisez: git submodule foreach
, par exemple.
git submodule foreach git pull Origin master -r