Кажется, что в этом обсуждении смешиваются два разных сценария:
Сценарий 1
Используя указатели моего родительского репозитория на подмодули, я хочу проверить фиксацию в каждом подмодуле, на который указывает родительский репозиторий, возможно, после первой итерации всех подмодулей и обновления / извлечения их из удаленного модуля.
Это, как указано, сделано с
git submodule foreach git pull origin BRANCH
git submodule update
Сценарий 2, на который, я думаю, нацелен OP
Новые вещи произошли в одном или нескольких подмодулях, и я хочу 1) вытащить эти изменения и 2) обновить родительский репозиторий, чтобы он указывал на HEAD (последний) коммит этого / этих подмодулей.
Это будет сделано
git submodule foreach git pull origin BRANCH
git add module_1_name
git add module_2_name
......
git add module_n_name
git push origin BRANCH
Не очень практично, поскольку вам придется жестко задавать n путей ко всем n подмодулям, например, в скрипте, чтобы обновить указатели фиксации родительского репозитория.
Было бы здорово иметь автоматическую итерацию для каждого подмодуля, обновляя указатель родительского репозитория (используя git add
), чтобы он указывал на заголовок подмодуля (ов).
Для этого я сделал небольшой скрипт Bash:
git-update-submodules.sh
#!/bin/bash
APP_PATH=$1
shift
if [ -z $APP_PATH ]; then
echo "Missing 1st argument: should be path to folder of a git repo";
exit 1;
fi
BRANCH=$1
shift
if [ -z $BRANCH ]; then
echo "Missing 2nd argument (branch name)";
exit 1;
fi
echo "Working in: $APP_PATH"
cd $APP_PATH
git checkout $BRANCH && git pull --ff origin $BRANCH
git submodule sync
git submodule init
git submodule update
git submodule foreach "(git checkout $BRANCH && git pull --ff origin $BRANCH && git push origin $BRANCH) || true"
for i in $(git submodule foreach --quiet 'echo $path')
do
echo "Adding $i to root repo"
git add "$i"
done
git commit -m "Updated $BRANCH branch of deployment repo to point to latest head of submodules"
git push origin $BRANCH
Чтобы запустить его, выполните
git-update-submodules.sh /path/to/base/repo BRANCH_NAME
разработка
Прежде всего, я предполагаю, что ветка с именем $ BRANCH (второй аргумент) существует во всех репозиториях. Не стесняйтесь сделать это еще сложнее.
Первая пара разделов посвящена проверке наличия аргументов. Затем я извлекаю последние материалы из родительского репозитория (я предпочитаю использовать --ff (ускоренная перемотка вперед) всякий раз, когда я просто выполняю вытягивание. У меня отключен ребаз, кстати).
git checkout $BRANCH && git pull --ff origin $BRANCH
Затем может потребоваться некоторая инициализация субмодуля, если новые субмодули были добавлены или еще не инициализированы:
git submodule sync
git submodule init
git submodule update
Затем я обновляю / тяну все подмодули:
git submodule foreach "(git checkout $BRANCH && git pull --ff origin $BRANCH && git push origin $BRANCH) || true"
Обратите внимание на несколько вещей: во-первых, я объединяю в цепочку некоторые команды Git, то &&
есть предыдущая команда должна выполняться без ошибок.
После возможного успешного извлечения (если новый материал был найден на удаленном компьютере) я делаю пуш, чтобы убедиться, что возможный коммит-слияние не остался на клиенте. Опять же, это происходит только в том случае, если тяга принесла новые вещи.
Наконец, в завершение необходимо || true
убедиться, что сценарий продолжает работу с ошибками. Чтобы это работало, все в итерации должно быть заключено в двойные кавычки, а команды Git заключены в круглые скобки (приоритет оператора).
Моя любимая часть:
for i in $(git submodule foreach --quiet 'echo $path')
do
echo "Adding $i to root repo"
git add "$i"
done
--quiet
Выполните итерацию всех подмодулей - с , который удаляет вывод 'Entering MODULE_PATH'. Используя 'echo $path'
(должно быть в одинарных кавычках), путь к подмодулю записывается в вывод.
Этот список относительных путей подмодулей записан в array ( $(...)
) - наконец, выполните итерации и выполните git add $i
обновление родительского репозитория.
Наконец, коммит с некоторым сообщением, объясняющим, что родительский репозиторий был обновлен. Этот коммит будет проигнорирован по умолчанию, если ничего не было сделано. Подтолкните это к источнику, и все готово.
У меня есть сценарий, выполняющий это в задании Jenkins, который впоследствии связывается с запланированным автоматическим развертыванием, и он работает как шарм.
Я надеюсь, что это кому-то поможет.
--remote
опцию, возможно, было бы полезно отметить это как принятый ответ, а не как «ручной» подход в ответе Джейсона?