git-pull-all — рекурсивно выполняет git pull --ff-only для текущей директории и всех вложенных git-репозиториев.
Путь в репозитории: bin/git-pull-all
🇬🇧 English | 🇷🇺 Русский | ⬅ Главная
Если у вас много git-репозиториев под одной общей папкой (~/projects/, ~/work/ и т.п.), git-pull-all обновит все одной командой. Каждый репозиторий тянется с --ff-only, поэтому разошедшаяся ветка громко падает, а не делает merge-коммит.
- Пробует
git pull --ff-onlyв текущей директории. - Находит все
.gitниже.(исключая внутренности.gitчерез-not -path '*/\.git/*'). - Для каждого найденного репозитория:
cd repo && git pull --ff-only. - Печатает
→ ошибка!для репо, где pull упал (расхождение веток, сетевая ошибка, нет upstream и т.д.).
Скрипт не прерывается на ошибке — проходит всё и отчитывается.
Исходник: bin/git-pull-all (~14 строк).
git(любая современная версия)- bash 3.2+ (системный на macOS) — на Linux тоже работает
- Заранее настроенная аутентификация:
ssh-agentс загруженными ключами, или- git credential helper (osxkeychain на macOS), или
- HTTPS-remotes без аутентификации (публичные репозитории)
Без преднастройки скрипт зависнет на запросе пароля для каждого репо.
chmod +x bin/git-pull-all # убедиться, что бит исполнения установлен
mkdir -p ~/bin
ln -s "$PWD/bin/git-pull-all" ~/bin/git-pull-all
# Убедиться, что ~/bin в PATH:
echo 'export PATH="$HOME/bin:$PATH"' >> ~/.zshrc
source ~/.zshrcИли запускать напрямую без установки:
bash bin/git-pull-allcd ~/projects # родительская папка с множеством репозиториев
git-pull-allПример вывода:
Обновляем корневой репозиторий...
Корень не обновлён (возможно, не репозиторий)
Обновляем все вложенные репозитории:
→ ./macos-utilities
Already up to date.
→ ./my-app
Updating a1b2c3d..e4f5g6h
Fast-forward
→ ./diverged-repo
→ ошибка!git pull --ff-only отказывается мёрджить, если локальная ветка разошлась с upstream. Это намеренно — защищает от тихих merge-коммитов. Цена: расходящиеся ветки пропускаются, вы увидите → ошибка!.
Если нужен merge или rebase — допилите скрипт или обработайте такие репо вручную.
Скрипт ищет независимые вложенные репозитории, а не git-submodules. Для submodules используйте git submodule update --remote отдельно.
Если репо требует пароль (и helper не настроен), скрипт зависнет на ожидании ввода. Таймаута нет.
Скрипт не пробрасывает ошибки через exit-код — они только печатаются в stdout. Чтобы ловить ошибки в CI, парсите stdout на → ошибка! или перепишите скрипт.
Статусные сообщения (Обновляем..., → ошибка!) на русском. Сам скрипт не локализован.
- Dry-run альтернатива:
git fetch --allв каждом репо покажет, что прилетит, без модификации рабочих копий. - Параллелизм: скрипт последовательный. Для многих больших репо можно распараллелить через
xargs -P, но осторожно с переплетающимся выводом. - Пропустить репо: встроенного механизма игнора нет. Либо вынесите репо за пределы поиска, либо форкните скрипт и добавьте фильтр путей.
Текущая директория не git-репо — всё в порядке, скрипт продолжит с вложенными.
- Проверьте сеть:
git ls-remote originв одном из репо. - Проверьте аутентификацию: ручной
git pull --ff-onlyв упавшем репо покажет реальную ошибку. - Расхождение веток:
git statusподскажет, опередила ли локальная ветка upstream или отстаёт.
Скорее всего ждёт ввод пароля. Ctrl+C и проверьте git pull в висящем репо вручную. Настройте ssh-agent или credential helper.