Запустите git потяните все подкаталоги

Как я могу обновить несколько репозиториев git из их общего родительского каталога без cd "в каждый корневой каталог репо? У меня есть следующие, которые являются отдельными репозиториями git (не):

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

Я хочу обновить их все сразу или, по крайней мере, упростить текущий рабочий процесс:

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

и др.

Ответ 1

Выполните следующее из родительского каталога plugins в этом случае:

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

Чтобы уточнить:

  • find . выполняет поиск текущего каталога
  • -type d для поиска каталогов, а не файлов
  • -depth 1 для максимальной глубины одного подкаталога
  • -exec {} \; запускает пользовательскую команду для каждого поиска
  • git --git-dir={}/.git --work-tree=$PWD/{} pull git извлекает отдельные каталоги

Чтобы поиграть с поиском, я рекомендую использовать echo после -exec для предварительного просмотра, например:

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

Примечание: если параметр -depth 1 недоступен, попробуйте -mindepth 1 -maxdepth 1.

Ответ 2

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

Чтобы сделать это параллельно:

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

Ответ 3

Немного более низкотехнологичное, чем лео-решение:

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

Это обновит все репозитории Git в вашем рабочем каталоге. Не нужно явно перечислять свои имена ( "cms", "admin", "chart" ). Команда "cd" влияет только на подоболочку (порожденную с помощью скобок).

Ответ 4

Это должно происходить автоматически, пока cms, admin и chart - все части репозитория.

Вероятная проблема заключается в том, что каждый из этих плагинов является подмодулем git.

Запустите git help submodule для получения дополнительной информации.

ИЗМЕНИТЬ

Для этого в bash:

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

Ответ 5

Я использую этот:

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

Universal: обновляет все репозитории git, которые находятся ниже текущего каталога.

Ответ 6

Утилита mr (a.k.a., myrepos) обеспечивает выдающееся решение этой проблемы. Установите его с помощью своего любимого менеджера пакетов или просто возьмите mr script непосредственно из github и поместите его в $HOME/bin или в другое место на вашем PATH. Затем cd в родительскую папку plugins, совместно используемую этими репозиториями, и создайте базовый файл .mrconfig с содержимым, аналогичным следующему (корректируя URL-адреса по мере необходимости):

# 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'

После этого вы можете запустить mr up из верхнего уровня plugins, чтобы извлекать обновления из каждого репозитория. (Обратите внимание, что это также сделает начальный клон, если целевая рабочая копия еще не существует.) Другие команды, которые вы можете выполнить, включают в себя mr st, mr push, mr log, mr diff и т.д. mr help чтобы увидеть, что возможно. Там есть команда mr run, которая действует как сквозной проход, позволяя вам получать доступ к командам VCS, которые непосредственно не поддерживаются самим mr (например, mr run git tag STAGING_081220015). И вы даже можете создавать свои собственные команды, которые выполняют произвольные бит оболочки script, предназначенные для всех репозиций!

mr - чрезвычайно полезный инструмент для работы с несколькими репозиториями. Поскольку папка plugins находится в вашем домашнем каталоге, вас также может заинтересовать vcsh. Вместе с mr он обеспечивает мощный механизм управления всеми вашими конфигурационными файлами. См. Этот сообщение в блоге от Thomas Ferris Nicolaisen для обзора.

Ответ 7

Самый компактный метод, предполагая, что все поддиректоры git repos:

ls | parallel git -C {} pull

Ответ 8

На самом деле, если вы не знаете, есть ли вложенные папки git repo или нет, лучше всего позволить find получить репозиции для вас:

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

Эквивалент PowerShell:

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

Ответ 9

Вы можете попробовать это

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

Кроме того, вы можете добавить свой индивидуальный вывод, добавив еще один && аргумент вроде.

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

Ответ 10

Ни один из 5 лучших ответов не работал у меня, и вопрос касался каталогов.

Это сработало:

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

Ответ 11

Оригинальный ответ 2010:

Если все эти каталоги являются отдельными репозиториями git, вы должны ссылаться на них как подмодули.

Это означает, что ваше "происхождение" будет таким удаленным репо "plugins", которое содержит только ссылки на подпозиции "cms", "admin", "chart".

A git pull, за которым следует a git submodule update, достигнет того, что вы ищете.


Обновление в январе 2016 года:

С git 2.8 (Q1 2016) вы сможете получить подмодули параллельно (!) с помощью git fetch --recurse-submodules -j2.
См. "Как ускорить/распараллелить загрузки подмодулей git с помощью git clone --recursive?"

Ответ 12

gitfox - это инструмент для выполнения команды во всех subppos

npm install gitfox -g
g pull

Ответ 13

Я использую этот

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

Github

Ответ 14

Поскольку у вас есть общий родительский каталог, вы можете просто сделать

git do pull в каталоге plugins/

Ответ 15

Я объединил точки из нескольких комментариев и ответов:

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

Ответ 16

Моя скромная конструкция, которая

  • показывает текущий путь (используя python, удобно и просто работает, см. Как получить полный путь к файлу?)
  • смотрит в подпапку .git: низкий шанс исправить команду git в подпапке git
  • избавляется от некоторых предупреждений find

следующим образом:

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

Конечно, вы можете добавить другие команды git с дополнительными параметрами -execdir в find, отображая ветвь, например:

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

Ответ 17

Если у вас много субдисков с репозиториями git, вы можете использовать параллельный

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
'