Есть ли способ заставить git pull автоматически обновлять подмодули?

203

Есть ли способ автоматически вызывать git submodule update(или предпочтительно git submodule update --initвызывать, когда git pullэто делается?)

Ищите настройки git config или псевдоним git, чтобы помочь с этим.

philfreo
источник
4
Связанный: stackoverflow.com/questions/1899792/…
philfreo
1
Почему псевдоним git предпочтительнее псевдонима оболочки?
Внуаз
20
Псевдонимы git хороши тем, что инкапсулируют команду в пространстве имен "git". Вы также можете спросить, почему все команды git начинаются с «git», а не имеют собственных имен.
Лили Баллард
5
Для тех, кто находит это, ответы с высоким рейтингом в настоящее время устарели. Ответ Кейна точен: stackoverflow.com/a/49427199/3499424
Джон Нейгауз,

Ответы:

176

Начиная с Git 2.14 , вы можете использовать git pull --recurse-submodules(и псевдоним это все, что вам нравится).

Начиная с Git 2.15 , вы можете установитьsubmodule.recurse значение true, чтобы включить желаемое поведение.

Вы можете сделать это глобально, запустив:

git config --global submodule.recurse true
Kane
источник
3
В соответствии с 2.16, установка этого значения в true также приведет git pullк получению субмодуля и запуску submodule update. Это действительно должен быть принятый ответ сейчас
Джон Нейгауз
1
Чтобы установить это глобально:git config --global submodule.recurse true
wintersolutions
14
Я был разочарован подмодулями, затем я сделал это. Теперь они работают так, как я ожидал. Есть ли причина, по которой я не думаю, что это не стандартное поведение?
Бен
9
Они должны включить это git cloneтакже. И сделать это по умолчанию. Иначе всегда будет огромное сопротивление использованию подмодулей, так как модули людей всегда не синхронизированы :-(
Ciro Santilli 郝海东 冠状 病 六四 事件 法轮功
1
@CiroSantilli新疆改造中心法轮功六四事件Сантилли мерзавец команд (например commit, fetch, pullи т.д.) предназначены для применения только к текущему хранилище. подмодуль является другим хранилищем и на него не должны влиять команды, выполняемые в родительском хранилище по умолчанию. это своего рода дизайнерское решение git-разработчика.
анион
113

git config --global alias.pullall '!git pull && git submodule update --init --recursive'

Если вы хотите, чтобы аргументы передавались в git pull, используйте вместо этого:

git config --global alias.pullall '!f(){ git pull "$@" && git submodule update --init --recursive; }; f'
Лили Баллард
источник
4
не забудьте использовать "git config --global", если вы хотите использовать этот псевдоним во всех используемых вами репозиториях git
yoyo
43

Начиная с Git 1.7.5, он должен автоматически обновлять подмодули по умолчанию, как вы этого хотите.

[EDIT: в комментариях: новый 1.7.5 поведение автоматически получать последние коммиты для подмодулей, но не для обновления их (вgit submodule update смысле). Таким образом, информация в этом ответе актуальна как справочная информация, но сама по себе она не является полным ответом. Вам все еще нужен псевдоним для извлечения и обновления подмодулей в одной команде.]

Поведение по умолчанию «по требованию» - обновлять субмодули всякий раз, когда вы выбираете коммит, который обновляет коммит субмодуля, а этот коммит еще не находится в вашем локальном клоне.
Вы также можете обновлять его при каждой загрузке или никогда (поведение до 1.7.5, я полагаю).
Параметр конфигурации, чтобы изменить это поведение fetch.recurseSubmodules.

Эта опция может быть установлена ​​либо в логическое значение, либо в on-demand.
Установка его в логическое значение изменяет поведение fetchи pullбезоговорочно переходить в подмодули, если задано значение true или вообще не рекурсивно, если задано значение false.

Если установлен в on-demand(значение по умолчанию), fetchи pull только рекурсии в населенный подмодуль , когда его суперпроект извлекает коммит , что обновления эталонного подмодуля в .

Видеть:

Чтобы получить больше информации.

git fetch --recurse-submodules[=yes|on-demand|no]
Кристофер Роджерс
источник
27
Остерегайтесь: как объясняют ответы ниже, это только извлекает изменения автоматически, вам все равно нужно выполнить обновление субмодуля - так что ответ псевдонима является правильным.
Артем
4
@ Артем правильный. Этот ответ, хотя и полезен, не охватывает весь вопрос. Этот параметр просто выполняет, а git fetchне git submodule update.
Эндрю Ферье
2
Этот ответ очень обманчив. Даже при использовании с git pull, а не с git fetch, эта опция только делает выборку рекурсивной. Это вообще не изменит то, что зафиксировано в подмодулях. Так git submodule updateчто все еще необходимо, как отмечает @Artem.
Марк Амери
31

Я удивлен, что никто не упомянул использование git hooks для этого!

Просто добавьте файлы с именами post-checkoutи post-mergeв свой .git/hooksкаталог соответствующих репозиториев, и поместите в каждый из них следующее:

#!/bin/sh
git submodule update --init --recursive

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

taleinat
источник
2
Есть ли способ сделать это глобальным параметром? Или тот, который вы получаете автоматически при проверке хранилища?
Рауль Штеффен
3
В последнем выпуске git, 2.9, добавлена ​​настройка, названная core.hooksPathдля каталога hooks , подробности см. В документации git-config.
taleinat
1
Что касается чего-то, полученного автоматически при оформлении заказа, я искал, но не мог найти ничего подобного. Один источник упомянул, что это намеренно не поддерживается из-за проблем безопасности, поскольку его довольно легко использовать для запуска произвольного кода на клиентских машинах.
taleinat
1
Я вижу, как это может быть проблемой безопасности. В конце концов, я хочу использовать его для запуска кода, который я программирую на компьютерах моих коллег, без необходимости их инструктировать.
Рауль Штеффен
1
Это решение было моей первой мыслью, но потом я понял, что оно не распространяется на людей, которые используют git pull --rebase:(
Vaz
8

Псевдоним, предложенный Кевином Баллардом, является отличным решением. Просто, чтобы бросить другой вариант, вы также можете использовать хук после слияния, который просто запускается git submodule update [--init].

Cascabel
источник
7

Вы можете создать псевдоним для команды git, которая автоматически обрабатывает обновление субмодуля. Добавьте следующее в ваш .bashrc

# make git submodules usable
#   This overwrites the 'git' command with modifications where necessary, and
#   calls the original otherwise
git() {
    if [[ $@ == clone* ]]; then
        gitargs=$(echo "$@" | cut -c6-)
        command git clone --recursive $gitargs
    elif [[ $@ == pull* ]]; then
        command git "$@" && git submodule update --init --recursive
    elif [[ $@ == checkout* ]]; then
        command git "$@" && git submodule update --init --recursive
    else
        command git "$@"
    fi
}
Бранден Гена
источник
1
Вместо псевдонима для git, вы можете добавить псевдонимы для git с помощью команды alias или создавая команды на своем пути, которые начинаются с git- (git-bettermodule)
idbrii
7

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

git config --global submodule.recurse true

Однако, если вы похожи на меня и имеете более сложную .gitconfigнастройку (мой основной ~/.gitconfigфайл используется includeдля загрузки в другие .gitconfigфайлы), и вы никогда не сможете вспомнить, как выполнить преобразование между gitформатом конфигурации командной строки и .gitconfigформатом, вот как его добавить. к любому из ваших .gitconfigфайлов:

[submodule]
  recurse = true
JacobEvelyn
источник
0

Единственный способ, которым я смог получить подмодули и вложенные подмодули для обновления:

git submodule update --remote --merge --recursive; git submodule foreach --recursive "(git add .; git commit -m 'SubmoduleSync'; git push; git pull;);" git add .; git commit -m 'SubmodulesSynced'; git push; git pull;

Я изо всех сил пытался создать псевдоним через терминал из-за скобок, поэтому мне пришлось вручную добавить это в .gitconfig для глобального:

[alias] supdate = "!git submodule update --remote --merge --recursive; git submodule foreach --recursive '(git add .; git commit -m 'SubmoduleSync'; git push; git pull;);' git add .; git commit -m 'SubmodulesSynced'; git push; git pull;"

Любые предложения о том, как запускать команды или псевдоним автоматически?

Саули Кивиранта
источник