Il semble que deux scénarios différents soient mélangés dans cette discussion:
Scénario 1
En utilisant les pointeurs de mon référentiel parent vers les sous-modules, je veux vérifier la validation dans chaque sous-module vers lequel pointe le référentiel parent, peut-être après avoir d'abord itéré tous les sous-modules et les avoir mis à jour / extraits à distance.
Ceci est, comme souligné, fait avec
git submodule foreach git pull origin BRANCH
git submodule update
Scénario 2, qui je pense est ce que vise OP
De nouvelles choses se sont produites dans un ou plusieurs sous-modules, et je veux 1) tirer ces modifications et 2) mettre à jour le référentiel parent pour pointer vers la validation HEAD (la plus récente) de ce / ces sous-modules.
Cela serait fait par
git submodule foreach git pull origin BRANCH
git add module_1_name
git add module_2_name
......
git add module_n_name
git push origin BRANCH
Pas très pratique, car il faudrait coder en dur n chemins vers tous les n sous-modules, par exemple dans un script pour mettre à jour les pointeurs de validation du référentiel parent.
Il serait intéressant d'avoir une itération automatisée à travers chaque sous-module, mettant à jour le pointeur du référentiel parent (à l'aide git add
) pour pointer vers la tête du ou des sous-modules.
Pour cela, j'ai réalisé ce petit script Bash:
git-update-submodules.sh
#!/bin/bash
APP_PATH=$1
shift
if [ -z $APP_PATH ]; then
echo "Missing 1st argument: should be path to folder of a git repo";
exit 1;
fi
BRANCH=$1
shift
if [ -z $BRANCH ]; then
echo "Missing 2nd argument (branch name)";
exit 1;
fi
echo "Working in: $APP_PATH"
cd $APP_PATH
git checkout $BRANCH && git pull --ff origin $BRANCH
git submodule sync
git submodule init
git submodule update
git submodule foreach "(git checkout $BRANCH && git pull --ff origin $BRANCH && git push origin $BRANCH) || true"
for i in $(git submodule foreach --quiet 'echo $path')
do
echo "Adding $i to root repo"
git add "$i"
done
git commit -m "Updated $BRANCH branch of deployment repo to point to latest head of submodules"
git push origin $BRANCH
Pour l'exécuter, exécutez
git-update-submodules.sh /path/to/base/repo BRANCH_NAME
Élaboration
Tout d'abord, je suppose que la branche avec le nom $ BRANCH (deuxième argument) existe dans tous les référentiels. N'hésitez pas à rendre cela encore plus complexe.
Les deux premières sections consistent à vérifier que les arguments sont là. Ensuite, je récupère les derniers éléments du référentiel parent (je préfère utiliser --ff (avance rapide) chaque fois que je fais des pulls. J'ai rebase off, BTW).
git checkout $BRANCH && git pull --ff origin $BRANCH
Ensuite, une initialisation de sous-module peut être nécessaire si de nouveaux sous-modules ont été ajoutés ou ne sont pas encore initialisés:
git submodule sync
git submodule init
git submodule update
Ensuite, je mets à jour / tire tous les sous-modules:
git submodule foreach "(git checkout $BRANCH && git pull --ff origin $BRANCH && git push origin $BRANCH) || true"
Remarquez quelques choses: Tout d'abord, je chaîne certaines commandes Git en utilisant &&
- ce qui signifie que la commande précédente doit s'exécuter sans erreur.
Après un éventuel pull réussi (si de nouveaux éléments ont été trouvés sur la télécommande), je fais un push pour m'assurer qu'un éventuel merge-commit n'est pas laissé sur le client. Encore une fois, cela ne se produit que si un pull a réellement apporté de nouvelles choses.
Enfin, la finale || true
s'assure que le script continue sur les erreurs. Pour que cela fonctionne, tout dans l'itération doit être encapsulé entre guillemets et les commandes Git sont encapsulées entre parenthèses (priorité de l'opérateur).
Ma partie préférée:
for i in $(git submodule foreach --quiet 'echo $path')
do
echo "Adding $i to root repo"
git add "$i"
done
Itérer tous les sous-modules - avec --quiet
, ce qui supprime la sortie «Entering MODULE_PATH». À l'aide de 'echo $path'
(doit être entre guillemets simples), le chemin d'accès au sous-module est écrit en sortie.
Cette liste de chemins de sous-module relatifs est capturée dans un tableau ( $(...)
) - enfin, répétez cela et faites git add $i
pour mettre à jour le référentiel parent.
Enfin, un commit avec un message expliquant que le référentiel parent a été mis à jour. Ce commit sera ignoré par défaut, si rien n'a été fait. Poussez ceci à l'origine, et vous avez terminé.
J'ai un script qui exécute cela dans un travail Jenkins qui s'enchaîne ensuite à un déploiement automatisé planifié, et cela fonctionne comme un charme.
J'espère que cela sera utile à quelqu'un.
--remote
option, il serait peut-être utile de marquer cela comme la réponse acceptée plutôt que l'approche "à la main" dans la réponse de Jason?