У меня есть проект с подмодулем Git. Он взят с URL-адреса ssh: // ... и находится в коммите 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
модулем и заново его добавлял, но это в принципе неправильно и утомительно на практике.
git
git-submodules
git-pull
Танатос
источник
источник
--remote
опцию, возможно, было бы полезно отметить это как принятый ответ, а не как «ручной» подход в ответе Джейсона?--remote
на данный момент определенно является лучшим решением, и, поскольку этот вопрос был связан с Github Gist о подмодулях, я думаю, что для новых читателей было бы лучше увидеть новый ответ.hunter2
Ответы:
Команда на
git submodule update
самом деле говорит Git, что вы хотите, чтобы ваши подмодули проверяли каждый коммит, уже указанный в индексе суперпроекта. Если вы хотите обновить свои подмодули до последнего коммита, доступного с их пульта, вам нужно будет сделать это прямо в подмодулях.Итак, в заключение:
Или, если вы занятой человек:
источник
git submodule foreach git pull
git submodule foreach git pull origin master
.git submodule foreach --recursive git pull origin master
.-a
Переключатель дляgit commit
«Скажите [s] команду автоматической установки файлов, которые были изменены и удалены, но новые файлы, о которых вы не сообщили Git, не затрагиваются».В Git 1.8.2 появилась новая опция
--remote
, которая включит именно это поведение. Бегизвлекает последние изменения из апстрима в каждом подмодуле, объединяет их и проверяет последнюю версию подмодуля. Как написано в документации :
Это эквивалентно запуску
git pull
в каждом подмодуле, что обычно именно то, что вы хотите.источник
git pull
в каждом подмодуле" Чтобы уточнить, нет разницы (с точки зрения пользователя) между вашим ответом иgit submodule foreach git pull
?foreach git pull
только проверил их, но не обновил указатель основного репо, чтобы он указывал на более новую фиксацию подмодуля. Только с--remote
этим он указал на последний коммит.В родительском каталоге вашего проекта запустите:
Или, если у вас есть рекурсивные подмодули, запустите:
Иногда это все еще не работает, потому что каким-то образом у вас есть локальные изменения в локальном каталоге подмодуля во время обновления подмодуля.
В большинстве случаев локальные изменения могут быть не теми, которые вы хотите зафиксировать. Это может произойти из-за удаления файла в вашем подмодуле и т. Д. Если это так, выполните сброс в локальном каталоге подмодуля и в родительском каталоге вашего проекта, запустите снова:
источник
Ваш основной проект указывает на конкретный коммит, в котором должен быть подмодуль.
git submodule update
пытается проверить этот коммит в каждом подмодуле, который был инициализирован. Подмодуль на самом деле является независимым репозиторием - просто создайте новый коммит в подмодуле и нажмите, что недостаточно. Вам также необходимо явно добавить новую версию субмодуля в основной проект.Итак, в вашем случае вы должны найти правильный коммит в подмодуле - давайте предположим, что это верхушка
master
:Теперь вернитесь к основному проекту, создайте подмодуль и передайте следующее:
Теперь нажмите вашу новую версию основного проекта:
С этого момента, если кто-то еще обновит свой основной проект, он
git submodule update
обновит субмодуль, предполагая, что он инициализирован.источник
Кажется, что в этом обсуждении смешиваются два разных сценария:
Сценарий 1
Используя указатели моего родительского репозитория на подмодули, я хочу проверить фиксацию в каждом подмодуле, на который указывает родительский репозиторий, возможно, после первой итерации всех подмодулей и обновления / извлечения их из удаленного модуля.
Это, как указано, сделано с
Сценарий 2, на который, я думаю, нацелен OP
Новые вещи произошли в одном или нескольких подмодулях, и я хочу 1) вытащить эти изменения и 2) обновить родительский репозиторий, чтобы он указывал на HEAD (последний) коммит этого / этих подмодулей.
Это будет сделано
Не очень практично, поскольку вам придется жестко задавать n путей ко всем n подмодулям, например, в скрипте, чтобы обновить указатели фиксации родительского репозитория.
Было бы здорово иметь автоматическую итерацию для каждого подмодуля, обновляя указатель родительского репозитория (используя
git add
), чтобы он указывал на заголовок подмодуля (ов).Для этого я сделал небольшой скрипт Bash:
git-update-submodules.sh
Чтобы запустить его, выполните
разработка
Прежде всего, я предполагаю, что ветка с именем $ BRANCH (второй аргумент) существует во всех репозиториях. Не стесняйтесь сделать это еще сложнее.
Первая пара разделов посвящена проверке наличия аргументов. Затем я извлекаю последние материалы из родительского репозитория (я предпочитаю использовать --ff (ускоренная перемотка вперед) всякий раз, когда я просто выполняю вытягивание. У меня отключен ребаз, кстати).
Затем может потребоваться некоторая инициализация субмодуля, если новые субмодули были добавлены или еще не инициализированы:
Затем я обновляю / тяну все подмодули:
Обратите внимание на несколько вещей: во-первых, я объединяю в цепочку некоторые команды Git, то
&&
есть предыдущая команда должна выполняться без ошибок.После возможного успешного извлечения (если новый материал был найден на удаленном компьютере) я делаю пуш, чтобы убедиться, что возможный коммит-слияние не остался на клиенте. Опять же, это происходит только в том случае, если тяга принесла новые вещи.
Наконец, в завершение необходимо
|| true
убедиться, что сценарий продолжает работу с ошибками. Чтобы это работало, все в итерации должно быть заключено в двойные кавычки, а команды Git заключены в круглые скобки (приоритет оператора).Моя любимая часть:
--quiet
Выполните итерацию всех подмодулей - с , который удаляет вывод 'Entering MODULE_PATH'. Используя'echo $path'
(должно быть в одинарных кавычках), путь к подмодулю записывается в вывод.Этот список относительных путей подмодулей записан в array (
$(...)
) - наконец, выполните итерации и выполнитеgit add $i
обновление родительского репозитория.Наконец, коммит с некоторым сообщением, объясняющим, что родительский репозиторий был обновлен. Этот коммит будет проигнорирован по умолчанию, если ничего не было сделано. Подтолкните это к источнику, и все готово.
У меня есть сценарий, выполняющий это в задании Jenkins, который впоследствии связывается с запланированным автоматическим развертыванием, и он работает как шарм.
Я надеюсь, что это кому-то поможет.
источник
pwd
выводит правильный «абсолютный путь» для каждого присутствующего подмодуля;--recursive
обеспечивает посещение всех подмодулей, включая подмодули внутри подмодулей -..., которые могут присутствовать в большом проекте. Оба метода вызывают проблемы с каталогами, которые содержат пробелы, например,/c/Users/Ger/Project\ Files/...
поэтому политика никогда не должна использовать пробелы в наших проектах.--remote
опцию.git submodule update --remote
ведет себя примерно так же, как ваш скрипт.The remote branch used defaults to master, but the branch name may be overridden by setting the submodule.<name>.branch option in either .gitmodules or .git/config (with .git/config taking precedence).
я не хочу редактировать ни .gitmodules, ни .git / config каждый раз, когда я хочу сделать это в другой ветке, кроме master. Но, может быть, я что-то пропустил? Кроме того, кажется, что этот метод обеспечивает рекурсивное слияние (таким образом, отсутствует возможность ускоренной перемотки вперед).Просто и понятно, чтобы получить подмодули:
А теперь перейдите к обновлению до последней ветки master (например):
источник
Обратите внимание, что современная форма обновления коммитов подмодулей будет выглядеть так:
Старая форма была:
За исключением ... эта вторая форма не очень "тихо".
См. Коммит а282f5a (12 апреля 2019 г.) Нгуен Тхай Нгук Дуй (
pclouds
) .(Объединено Junio C Hamano -
gitster
- в коммите f1c9f6c , 25 апреля 2019 г.)А в Git 2.23 (Q3 2019) исправлена другая проблема: «
git submodule foreach
» не защищал параметры командной строки, передаваемые команде для правильного запуска в каждом подмодуле, когда использовалась--recursive
опция « ».См. Коммит 30db18b (24 июня 2019 г.) от Morian Sonnet (
momoson
) .(Слиты Junio C Hamano -
gitster
- в фиксации 968eecb , 9 июля 2019)источник
Это потянет все последние коммиты.
источник
В моем случае я хотел
git
обновить до последней версии и в то же время повторно заполнить все отсутствующие файлы.Следующее восстановило отсутствующие файлы (спасибо,
--force
что, кажется, здесь не упоминалось), но не получило никаких новых коммитов:git submodule update --init --recursive --force
Это сделал:
git submodule update --recursive --remote --merge --force
источник
@ Джейсон правильно, но не совсем.
Итак,
git submodule update
делает извлечение, но это для фиксации в индексе содержащего репозитория. Он еще не знает о новом коммите вверх по течению. Перейдите в свой подмодуль, получите нужный коммит и зафиксируйте обновленное состояние подмодуля в основном репозитории, а затем выполнитеgit submodule update
.источник
git submodule update
, обновление переместит субмодуль в коммит, который указан в текущем HEAD суперпроекта. (что бы ни говорилось в самом последнем коммите в суперпроекте - подпроект должен быть при этом - такое поведение после объяснения в посте Джейсона кажется мне логичным) Оно также кажется извлекаемым, но только в том случае, если подпроект находится на неправильном коммите , что добавляло к моему замешательству.Вот потрясающий однострочник, чтобы обновить все до последней версии на мастере:
Благодаря Марку Жакиту
источник
Если вы не знаете ветку хоста, сделайте так:
Он получит ветку основного репозитория Git, а затем для каждого подмодуля сделает тягу из той же ветки.
источник
Если вы ищете
master
ветку оформления для каждого подмодуля - вы можете использовать следующую команду для этой цели:источник