Обновить подмодуль Git до последней фиксации в origin



у меня есть проект с подмодулем Git. Это из ssh://... URL, и находится на фиксации A. фиксация B была перенесена на этот URL, и я хочу, чтобы подмодуль извлек фиксацию и изменил ее.



теперь я понимаю, что git submodule update должен делать это, но это не так. Он ничего не делает (нет вывода, успех код выхода). Вот пример:



$ mkdir foo
$ cd foo
$ git init .
Initialized empty Git repository in /.../foo/.git/
$ git submodule add ssh://user@host/git/mod mod
Cloning into mod...
user@host's password: hunter2
remote: Counting objects: 131, done.
remote: Compressing objects: 100% (115/115), done.
remote: Total 131 (delta 54), reused 0 (delta 0)
Receiving objects: 100% (131/131), 16.16 KiB, done.
Resolving deltas: 100% (54/54), done.
$ git commit -m "Hello world."
[master (root-commit) 565b235] Hello world.
2 files changed, 4 insertions(+), 0 deletions(-)
create mode 100644 .gitmodules
create mode 160000 mod
# At this point, ssh://user@host/git/mod changes; submodule needs to change too.
$ git submodule init
Submodule 'mod' (ssh://user@host/git/mod) registered for path 'mod'
$ git submodule update
$ git submodule sync
Synchronizing submodule url for 'mod'
$ git submodule update
$ man git-submodule
$ git submodule update --rebase
$ git submodule update
$ echo $?
0
$ git status
# On branch master
nothing to commit (working directory clean)
$ git submodule update mod
$ ...


Я тоже пробовал git fetch mod, который, кажется, делает выборку (но не может, потому что он не запрашивает для пароля!), но git log и git show отрицают существование новых коммитов. До сих пор я просто rm-ing модуль и повторное добавление его, но это и неправильно в принципе и утомительно на практике.

881   9  

9 ответов:

The git submodule update команда фактически сообщает Git, что вы хотите, чтобы ваши подмодули каждый раз проверяли фиксацию, уже указанную в индексе суперпроекта. Если вы хотите обновление ваши подмодули до последней фиксации, доступной с их пульта дистанционного управления, вам нужно будет сделать это непосредственно в подмодулях.

таким образом:

# get the submodule initially
git submodule add ssh://bla submodule_dir
git submodule init

# time passes, submodule upstream is updated
# and you now want to update

# change to the submodule directory
cd submodule_dir

# checkout desired branch
git checkout master

# update
git pull

# get back to your project root
cd ..

# now the submodules are in the state you want, so
git commit -am "Pulled down update to submodule_dir"

или, если вы занятой человек:

git submodule foreach git pull origin master

Git 1.8.2 имеет новую опцию --remote Это позволит точно такое поведение. Работает

git submodule update --remote --merge

будет извлекать последние изменения из восходящего потока в каждом подмодуле, объединять их и проверять последнюю версию подмодуля. Как документы это:

--remote

эта опция действительна только для команды update. Вместо использования записали суперпроекты по алгоритму SHA-1, чтобы обновить субмодуль, использовать статус ветвь дистанционного слежения подмодуля.

Это эквивалентно запуску git pull в каждом подмодуле, который, как правило, именно то, что вы хотите.

в Родительском каталоге проекта выполните:

git submodule update --init 

или если у вас есть рекурсивные подмодули run:

git submodule update --init --recursive

иногда это все еще не работает, потому что каким-то образом у вас есть локальные изменения в локальном каталоге подмодуля во время обновления подмодуля.

большую часть времени локальное изменение может быть не тем, которое вы хотите зафиксировать. Это может произойти из-за удаления файла в вашем подмодуле и т. д. Если это так, выполните сброс в локальном каталоге подмодуля и в вашем Родительском каталоге проекта снова запустите:

git submodule update --init --recursive 

ваш основной проект указывает на конкретную фиксацию, в которой должен быть подмодуль. Что git submodule update делает это, чтобы попытаться кассе, которые совершают в каждом подмодуле, был инициализирован. Подмодуль действительно является независимым репозиторием - просто создайте новую фиксацию в подмодуле и нажмите, что этого недостаточно, вам также нужно явно добавить новую версию подмодуля в основной проект.

Итак, в вашем случае вы должны найти правильный коммит в подмодуле-давайте предположим, что это подсказка мастера:

cd mod
git checkout master
git pull origin master

теперь вернитесь к основному проекту, поставьте подмодуль и зафиксируйте это:

cd ..
git add mod
git commit -m "Updating the submodule 'mod' to the latest version"

теперь нажмите вашу новую версию основного проекта:

git push origin master

С этого момента, если кто-то обновляет свой основной проект, то git submodule update для них будет обновляться подмодуль, предполагая, что он был инициализирован.

похоже, что в этом обсуждении смешиваются 2 разных сценария:

Сценарий 1

используя указатели моего родительского РЕПО на подмодули, я хочу проверить фиксацию в каждом подмодуле, на который указывает родительское РЕПО, возможно, после первого перебора всех подмодулей и обновления/извлечения их из удаленного.

это, как было указано, Сделано с

git submodule foreach git pull origin BRANCH
git submodule update

Сценарий 2, который я подумайте, к чему стремится ОП

новые вещи произошли в 1 или более подмодулях, и я хочу 1) вытащить эти изменения и 2) обновить родительское репо, чтобы указать на головную (последнюю) фиксацию этого/этих подмодулей.

это будет сделано с помощью

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=
shift

if [ -z $APP_PATH ]; then
  echo "Missing 1st argument: should be path to folder of a git repo";
  exit 1;
fi

BRANCH=
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 (2-й аргумент) существует на всех РЕПО. Не стесняйтесь сделать это еще более сложным.

первая пара разделов-это проверка того, что аргументы есть. Затем я вытаскиваю последние вещи родительского РЕПО (я предпочитаю использовать --ff (fast-forwarding) всякий раз, когда я просто делаю pulls. У меня есть rebase off, кстати).

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-обернуты в parantheses (приоритет оператора).

моя любимая часть:

for i in $(git submodule foreach --quiet 'echo $path')
do
  echo "Adding $i to root repo"
  git add "$i"
done

повторите все подмодули-с --quiet, который удаляет вывод "ввод MODULE_PATH". Используя 'echo $path' (должно быть в одинарных кавычках), путь к подмодулю записывается на выход.

этот список относительный пути подмодуля захватываются в массив ($(...)) - наконец повторите это и сделайте git add $i для обновления родительского РЕПО.

наконец, фиксация с некоторым сообщением, объясняющим, что родительское РЕПО было обновлено. Эта фиксация будет проигнорирована по умолчанию, если ничего не было сделано. Подтолкните это к origin, и все готово.

у меня есть скрипт, выполняющий это в Jenkins-job, который впоследствии подключается к запланированному автоматическому развертыванию, и он работает как шарм.

я надеюсь это кому-то поможет.

простой и простой, чтобы получить подмодули:

git submodule update --init --recursive

а теперь продолжайте обновлять их до последней главной ветви (например):

git submodule foreach git pull origin master

@Джейсон прав в некотором смысле, но не полностью.

обновление

обновить зарегистрированные подмодули, т. е. клонировать недостающие подмодули и проверка фиксации, указанной в индекс содержащего репозитория. Это сделает голову подмодулей быть отсоединяется, если только --rebase или --merge не является указанный или ключ подмодуль.$имя.обновление имеет значение rebase или слияния.

Итак, обновление подмодуля git делает проверку, но дело в том, это фиксация в индексе содержащего репозитория. Он еще не знает о новой фиксации вверх по течению вообще. Поэтому перейдите в свой подмодуль, получите фиксацию, которую вы хотите, и зафиксируйте обновленное состояние подмодуля в главном РЕПО, а затем выполните git submodule update

вот удивительный один лайнер, чтобы обновить все до последней версии на master:

git submodule foreach 'git fetch origin --tags; git checkout master; git pull' && git pull && git submodule update --init --recursive

спасибо Mark Jaquith

в моем случае, я хотел git для обновления до последней версии и в то же время повторно заполнить все отсутствующие файлы.

следующие восстановили отсутствующие файлы (благодаря --force который, похоже, не упоминался здесь), но он не вытащил никаких новых коммитов:

git submodule update --init --recursive --force

это сделал:

git submodule update --recursive --remote --merge --force

Comments

    Ничего не найдено.