2010-08-16 16 views
140

¿Cómo puedo actualizar varios repositorios de git del directorio padre compartido sin cd 'en el directorio raíz de cada repositorio? Tengo los siguientes, que son todos los repositorios Git separados (no submódulos):Ejecutar git pull over en todos los subdirectorios

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

Quiero actualizar todos a la vez o al menos simplificar mi flujo de trabajo actual:

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

etc.

+4

Qué le pasa a 'find -name .git -execdir git pull \; '? – jthill

+0

¿Qué pasa con 'git do pull' –

+0

La misma pregunta [respondida] (https://stackoverflow.com/a/48790388/2192488) para' hg mercurial'. –

Respuesta

198

ejecute lo siguiente desde el directorio padre, plugins en este caso:

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

Para aclarar:

  • find . búsquedas del directorio actual
  • -type d para encontrar directorios, no archivos
  • -depth 1 para una profundidad máxima de un subdirectorio
  • -exec {} \; ejecuta un comando personalizado para cada encontrar
  • git --git-dir={}/.git --work-tree=$PWD/{} pull git tira de los directorios individuales

jugar con hallazgo, recomiendo el uso de echo después -exec a vista previa, por ejemplo:

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

Nota: si la opción -depth 1 no está disponible, trate -mindepth 1 -maxdepth 1.

+0

Gracias @batandwa por su comentario sobre el uso de -d. – leo

+9

encontrar: advertencia: ha especificado la opción -depth después de un argumento no opcional -type, pero las opciones no son posicionales (-depth afecta a las pruebas especificadas antes, así como a las especificadas después). Por favor, especifique las opciones antes que otros argumentos. – Yurik

+21

He usado 'encontrar. -maxdepth 1 -type d -print -execdir git --git-dir = {} /.git -work-tree = $ PWD/{} pull master de origen \; 'para generar el nombre de la carpeta antes de realizar la extracción, para deshacerse de la advertencia y ejecutar solo las subcarpetas de extracción. – Rystraum

11

Esto debería suceder automáticamente, siempre que cms, admin y chart sean todas partes del repositorio.

Un problema probable es que cada uno de estos complementos es un submódulo de git. Para obtener más información, ejecute para obtener más información.

EDITAR

Para hacer esto en bash:

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

No, siento que hayas malentendido. Cada uno de esos directorios es un repositorio git separado. '/ plugins' no es un repositorio – Petah

+0

Ahhh. Mi error. Te dará la solución bash en un minuto. –

+0

Ahí tienes. Si desea regresar al directorio principal, simplemente ejecute otro 'cd ..' luego. –

1

Respuesta original 2010:

Si todos esos directorios son repositorio git separada, se debe hacer referencia a ellos como submodules .

Eso significa que su "origen" habría que reporto a distancia 'plugins' que sólo contiene referencias a subrepos 'cms', 'admin', 'chart'.

A git pull seguido de git submodule update lograr lo que estás buscando.


actualización de enero de 2016:

Con Git 2,8 (Q1 2016), usted será capaz de ir a buscar a los submódulos en paralelo con git fetch --recurse-submodules -j2 (!).
Ver "How to speed up/parallelize downloads of git submodules using git clone --recursive?"

+1

Vea también http://stackoverflow.com/questions/1979167/git-submodule-update y http://stackoverflow.com/questions/1030169/git-easy-way-pull-latest-of-all-submodules: ' git submodule foreach git pull' también puede ser de interés. – VonC

+0

Nota: para aclarar, '' plugins' ', que no es un git repo en este momento, debe hacerse uno, como un repositorio padre de git para los submódulos. – VonC

22

un poco más baja tecnología que la solución de leo:

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

Esto actualizará todos los repositorios Git en su directorio de trabajo. No es necesario enumerar explícitamente sus nombres ("cms", "admin", "chart"). El comando "cd" solo afecta a una subcadena (generada usando el paréntesis).

+0

Exactamente lo que estaba buscando – GameSalutes

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

hacerlo en paralelo:

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

¡Bonito! Lo puse como un alias en mi .gitconfig: 'all ="! F() {ls | xargs -I {} git -C {} $ 1;}; f "' Ahora puedo hacer 'git all pull' , 'git todos "checkout master"' etc. – borisdiakur

+2

se ha limpiado un poco, va a buscar todos los directorios de forma recursiva sólo para repositorios Git, y eliminará los colores en caso de tener ls 'alias ls -R --directory -color = Nunca * /. git | sed 's/\ /. git //' | xargs -P10 -I {} {} -C git pull' – cchamberlain

+0

Aquí está el comando git config para agregarlo como un alias: git config alias.all --global 'f() {ls |! xargs -I {} git -C {} $ 1; }; f' – simonbogarde

2

puede probar esta

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

Además, se puede añadir su salida personalizado mediante la adición de una más & & argumentos similares.

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

Si usted tiene una gran cantidad de subdirectorios con repositorios git, se puede utilizar en paralelo

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 
' 
+0

Genial. Modifiqué un poco para adaptarme a mi estilo. [pastebin] (http://pastebin.com/U7SMszkP) – maricn

7

La utilidad mr (alias, myrepos) proporciona una solución excepcional a este mismo problema. Instálelo utilizando su administrador de paquetes favorito, o simplemente tome el script mrdirectly from github y póngalo en $HOME/bin o en otro lugar en su PATH. Entonces, cd a la carpeta principal plugins compartida por estos repos y crear un archivo básico .mrconfig con contenidos similares a los siguientes (ajuste de las direcciones URL según sea necesario):

# File: .mrconfig 
[cms] 
checkout = git clone 'https://<username>@github.com/<username>/cms' 'cms' 

[admin] 
checkout = git clone 'https://<username>@github.com/<username>/admin' 'admin' 

[chart] 
checkout = git clone 'https://<username>@github.com/<username>/chart' 'chart' 

Después de eso, puede ejecutar mr up desde el nivel superior plugins carpeta para extraer actualizaciones de cada repositorio. (Tenga en cuenta que esto también hará la copia inicial si la copia de trabajo objetivo aún no existe.) Otros comandos que puede ejecutar incluyen mr st, mr push, mr log, mr diff, etc., ejecute mr help para ver qué es posible. Hay un comando mr run que actúa como paso a través, lo que le permite acceder a los comandos de VCS que no son directamente compatibles con mr (por ejemplo, mr run git tag STAGING_081220015). ¡Incluso puede crear sus propios comandos personalizados que ejecutan bits arbitrarios de script de shell dirigidos a todos los repositorios!

mr es una herramienta extremadamente útil para tratar múltiples repositorios. Dado que la carpeta plugins está en su directorio de inicio, también podría estar interesado en vcsh. Junto con mr, proporciona un poderoso mecanismo para administrar todos de sus archivos de configuración. Consulte esto blog post por Thomas Ferris Nicolaisen para una descripción general.

7

método más compacta, suponiendo que todos los sub-directorios son repositorios git:

ls | parallel git -C {} pull 
10

que utilizo éste:

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

universal: Actualiza todos los repositorios Git que están por debajo del directorio actual.

0

Yo uso este

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

Github

2

Ninguno de los 5 mejores respuestas trabajó para mí, y la cuestión hablado de directorios.

Esto funcionó:

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

En realidad, si no saber si las subcarpetas tienen un repositorio git o no, lo mejor sería dejar que find obtener los repositorios para usted:

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

El PowerShell equivalente sería:

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

Esto funciona con mis macOS. –

2

gitfox es una herramienta para ejecutar comando en todos los subrepos

npm install gitfox -g 
g pull 
+0

¿Qué es 'g'? no todos tienen el mismo alias que el suyo –

+1

@ LưuVĩnhPhúc gitfox se instala bajo el alias "g" por algún motivo (aunque el mensaje de ayuda dice "gitfox"). Personalmente, no creo que sea un comando lo suficientemente importante como para reclamar un atajo, pero bueno. Hace el trabajo, sin embargo. – Stoffe

+0

@ LưuVĩnhPhúc Compruebe el repositorio de origen para el uso https://github.com/eqfox/gitfox – thuanle

1

combiné puntos de varios comentarios y respuestas:

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

Mi humilde construcción que

  • muestra la ruta actual (usando pitón, conveniente y simplemente funciona, vea How to get full path of a file?)
  • mira directamente para la subcarpeta .git: oportunidad baja t o emitir un comando git en una subcarpeta no git
  • se deshace de algunas advertencias de find

de la siguiente manera:

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

Por supuesto, es posible añadir otros comandos git con -execdir opciones adicionales a find, mostrando la rama por ejemplo:

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