Exécuter git pull sur tous les sous-répertoires

Comment puis-je mettre à jour plusieurs référentiels git depuis le répertoire de leurs parents partagés sans les insérer dans le répertoire racine de chaque repository? J’ai les éléments suivants qui sont tous des repositorys git séparés ( pas des sous-modules):

 /plugins/cms /plugins/admin /plugins/chart 

Je veux les mettre à jour en même temps ou au moins simplifier mon stream de travail actuel:

 cd ~/plugins/admin git pull origin master cd ../chart git pull 

etc.

Exécutez les éléments suivants à partir du répertoire parent, plugins dans ce cas:

 find . -type d -depth 1 -exec git --git-dir={}/.git --work-tree=$PWD/{} pull origin master \; 

Clarifier:

  • find . recherche dans le répertoire en cours
  • -type d pour trouver des répertoires, pas des fichiers
  • -depth 1 pour une profondeur maximale d’un sous-répertoire
  • -exec {} \; exécute une commande personnalisée pour chaque recherche
  • git --git-dir={}/.git --work-tree=$PWD/{} pull les répertoires individuels

Pour jouer avec find, je recommande d’utiliser echo after -exec pour prévisualiser, par exemple:

 find . -type d -depth 1 -exec echo git --git-dir={}/.git --work-tree=$PWD/{} status \; 

Remarque: si l’option -depth 1 n’est pas disponible, essayez -mindepth 1 -maxdepth 1 .

 ls | xargs -I{} git -C {} pull 

Pour le faire en parallèle:

 ls | xargs -P10 -I{} git -C {} pull 

Un peu plus low-tech que la solution de leo:

 for i in */.git; do ( echo $i; cd $i/..; git pull; ); done 

Cela mettra à jour tous les référentiels Git dans votre répertoire de travail. Pas besoin de lister explicitement leurs noms (“cms”, “admin”, “chart”). La commande “cd” n’affecte qu’un sous-shell (généré à l’aide de la parenthèse).

J’utilise celui-ci:

 find . -name ".git" -type d | sed 's/\/.git//' | xargs -P10 -I{} git -C {} pull 

Universel: Met à jour tous les référentiels git situés sous le répertoire actuel.

Cela devrait se produire automatiquement, à condition que cms, admin et chart soient tous des parties du référentiel.

Un problème probable est que chacun de ces plugins est un sous-module git.

Exécutez le git help submodule pour plus d’informations.

MODIFIER

Pour faire cela en bash:

 cd plugins for f in cms admin chart do cd $f && git pull origin master && cd .. done 

L’utilitaire mr (aka myrepos ) fournit une solution exceptionnelle à ce problème. Installez-le en utilisant votre gestionnaire de paquets préféré, ou saisissez simplement le script mr directement depuis github et placez-le dans $HOME/bin ou ailleurs dans votre PATH . Ensuite, cd dans le dossier des plugins parents partagés par ces repos et créez un fichier .mrconfig base avec un contenu similaire à celui-ci (en ajustant les URL si nécessaire):

 # File: .mrconfig [cms] checkout = git clone 'https://@github.com//cms' 'cms' [admin] checkout = git clone 'https://@github.com//admin' 'admin' [chart] checkout = git clone 'https://@github.com//chart' 'chart' 

Après cela, vous pouvez exécuter mr up partir du dossier plugins niveau supérieur pour extraire les mises à jour de chaque référentiel. (Notez que ceci fera aussi le clone initial si la copie de travail cible n’existe pas encore.) D’autres commandes que vous pouvez exécuter incluent mr st , mr push , mr log , mr diff , etc. – lancez mr help pour voir ce qui est possible. Il existe une commande mr run qui fait office d’intermédiaire, vous permettant d’accéder aux commandes VCS qui ne sont pas directement supscopes par mr (par exemple, mr run git tag STAGING_081220015 ). Et vous pouvez même créer vos propres commandes personnalisées qui exécutent des bits de script shell arbitraires ciblant tous les repos!

mr est un outil extrêmement utile pour traiter les mises en pension multiples. Étant donné que le dossier plugins trouve dans votre répertoire personnel, vous pouvez également être intéressé par vcsh . Avec mr , il fournit un mécanisme puissant pour gérer tous vos fichiers de configuration. Voir ce billet de Thomas Ferris Nicolaisen pour un aperçu.

En fait, si vous ne savez pas si les sous-dossiers ont un repo git ou non, le mieux serait de vous laisser find les pensions:

 find . -type d -name .git -exec git --git-dir={} --work-tree=$PWD/{}/.. pull origin master \; 

L’équivalent PowerShell serait:

 Get-ChildItem -Recurse -Directory -Hidden -Filter .git | ForEach-Object { & git --git-dir="$($_.FullName)" --work-tree="$(Split-Path $_.FullName -Parent)" pull origin master } 

La méthode la plus compacte, en supposant que tous les sous-répertoires soient git repos:

 ls | parallel git -C {} pull 

gitfox est un outil pour exécuter des commandes sur toutes les sous-positions

 npm install gitfox -g g pull 

Vous pouvez essayer ceci

 find . -type d -name .git -exec sh -c "cd \"{}\"/../ && pwd && git pull" \; 

En outre, vous pouvez append votre sortie personnalisée en ajoutant un argument && tel que.

 find . -type d -name .git -exec sh -c "cd \"{}\"/../ && pwd && git pull && git status" \; 

Aucune des 5 premières réponses n’a fonctionné pour moi, et la question portait sur les répertoires.

Cela a fonctionné:

 for d in *; do pushd $d && git pull && popd; done 

Réponse originale 2010:

Si tous ces répertoires sont séparés de git repo, vous devez les référencer en tant que sous-modules .

Cela signifie que votre “origine” serait ce ” plugins in” de repo distant qui contient uniquement des références aux sous-positions ” cms “, ” admin “, ” chart “.

Un git pull suivi d’une git submodule update permettrait d’atteindre ce que vous recherchez.


Mise à jour janvier 2016:

Avec Git 2.8 (Q1 2016), vous pourrez récupérer des sous-modules en parallèle (!) Avec git fetch --recurse-submodules -j2 .
Voir ” Comment accélérer / paralléliser les téléchargements de sous-modules git en utilisant git clone –recursive? ”

J’ai combiné des points de plusieurs commentaires et réponses:

 find . -maxdepth 1 -type d -name .git -execdir git pull \; 

Je l’utilise

 for dir in $(find . -name ".git") do cd ${dir%/*} echo $PWD git pull echo "" cd - > /dev/null done 

Github

Ma construction humble

  • montre le chemin actuel (en utilisant python, pratique et fonctionne, voir Comment obtenir le chemin complet d’un fichier? )
  • recherche directement le sous-dossier .git : faible chance d’émettre une commande git dans un sous-dossier non-git
  • se débarrasse de certains avertissements de find

comme suit:

 find . \ -maxdepth 2 -type d \ -name ".git" \ -execdir python -c 'import os; print(os.path.abspath("."))' \; \ -execdir git pull \; 

Bien sûr, vous pouvez append d’autres commandes git avec des options -execdir supplémentaires pour afficher la twig, par exemple:

 find . \ -maxdepth 2 -type d \ -name ".git" \ -execdir python -c 'import os; print(os.path.abspath("."))' \; \ -execdir git branch \; -execdir git pull \; 

Si vous avez beaucoup de sous-répertoires avec des référentiels git, vous pouvez utiliser parallèlement

 ls | parallel -I{} -j100 ' if [ -d {}/.git ]; then echo Pulling {} git -C {} pull > /dev/null && echo "pulled" || echo "error :(" else echo {} is not a .git directory fi '