2010-08-16 3 views
140

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

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

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

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

и т.д.

+4

Что случилось с 'найти -name .git -execdir мерзавец тянуть \; '? – jthill

+0

как насчет 'git do pull' –

+0

Тот же вопрос [ответил] (https://stackoverflow.com/a/48790388/2192488) для' hg mercurial'. –

ответ

198

Выполните следующую из родительского каталога, 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 мерзавец тянет отдельные каталоги

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

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

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

+0

Спасибо @batandwa за ваше замечание об использовании -d. – leo

+9

find: warning: вы указали опцию -depth после типа аргумента non-option, но параметры не являются позиционными (-depth влияет на тесты, указанные перед ним, а также те, которые указаны после него). Пожалуйста, укажите параметры перед другими аргументами. – Yurik

+21

Я использовал 'find. -maxdepth 1-type d -print -execdir git --git-dir = {} /.git -work-tree = $ PWD/{} вытащить исходный мастер \; 'для вывода имени папки перед выполнением pull, чтобы избавиться от предупреждения и только запустить pull на подпапках. – Rystraum

11

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

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

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

EDIT

Для делать это в Баш:

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

Нет, извините, вы неправильно поняли. Каждый из этих каталогов представляет собой отдельный репозиторий git. '/ plugins' не является репозиторием – Petah

+0

Ahhh. Виноват. Дает вам решение bash через минуту. –

+0

Там вы идете. Если вы хотите вернуться в родительский каталог, просто запустите еще один 'cd ..'. –

1

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

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

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

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


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

С Git 2.8 (Q1 2016), вы будете иметь возможность получать подмодулях параллельно с git fetch --recurse-submodules -j2 (!).
См "How to speed up/parallelize downloads of git submodules using git clone --recursive?"

+1

См. Также http://stackoverflow.com/questions/1979167/git-submodule-update и http://stackoverflow.com/questions/1030169/git-easy-way-pull-latest-of-all-submodules: ' git subodule foreach git pull' также может представлять интерес. – VonC

+0

Примечание: чтобы уточнить, «плагины», которые в настоящий момент не являются репозиторией git, должны быть сделаны одним, как родительское git-репо для подмодулей. – VonC

22

немного более высокие технологии, чем решение Лео:

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

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

+0

Точно что я искал – GameSalutes

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

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

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

Nice! Я поместил его как псевдоним в свой .gitconfig: 'all ="! F() {ls | xargs -I {} git -C {} $ 1;}; f "' Теперь я могу сделать git all pull' , 'git all" checkout master "' и т. д. – borisdiakur

+2

Убрал немного, будет искать все каталоги рекурсивно только для git-репозиториев и будет выделять цвета, если вы ls-aliased 'ls -R -directory --color = never * /. git | sed 's/\ /. git //' | xargs -P10 -I {} git -C {} pull' – cchamberlain

+0

Вот команда git config, чтобы добавить ее как псевдоним: git config --global alias.all '! f() {ls | xargs -I {} git -C {} $ 1; }; f ' – simonbogarde

2

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

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" \; 
-1

Если у вас есть много подкаталогов с 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 
' 
+0

Отличный. Я немного изменил свой стиль. [pastebin] (http://pastebin.com/U7SMszkP) – maricn

7

The mr утилиты (а.к.а., myrepos) обеспечивает выдающийся решение этой самой проблемы. Установите его с помощью своего любимого менеджера пакетов или просто возьмите сценарий mrdirectly from 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). И вы даже можете создавать свои собственные команды, которые выполняют произвольные биты сценария оболочки, нацеленные на все репозитории!

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

7

Наиболее компактный метод, предполагая, что все вложенные каталоги являются Git репо:

ls | parallel git -C {} pull 
10

Я это один использовать:

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

Универсальный: Обновление всех Git репозитории, которые находятся ниже текущей директории.

0

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

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

Github

2

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

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

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

На самом деле, если вы не знаете, если вложенные папки имеют GIT репозиторий или нет, то лучше было бы, чтобы 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 } 
+0

Это работает с моим macOS. –

2

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

npm install gitfox -g 
g pull 
+0

что это 'g'? не все имеют тот же псевдоним, что и ваш –

+1

@ LưuVĩnhPhúc gitfox устанавливается под псевдонимом «g» по какой-либо причине (хотя в справочном сообщении говорится «gitfox»). Лично я не думаю, что это достаточно важная команда, чтобы требовать такой ярлык, но хорошо. Однако он выполняет эту работу. – Stoffe

+0

@ LưuVĩnhPhúc Проверьте исходное репо на использование https://github.com/eqfox/gitfox – thuanle

1

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

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

Мое скромное сооружение,

  • показывает текущий путь (с помощью питона, удобно и просто работает, см. How to get full path of a file?)
  • смотрит прямо на .git вложенные пачки: низкая вероятность t о испустить команду 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 \; 
Смежные вопросы