Легкий способ вытащить последние из всех подмодулей git

Мы используем подмодули git для управления парой крупных проектов, которые зависят от многих других библиотек, которые мы разработали. Каждая библиотека представляет собой отдельный репозиторий, внесенный в зависимый проект в виде подмодуля. Во время разработки мы часто хотим просто взять последнюю версию каждого зависимого подмодуля.

Есть ли в git встроенная команда для этого? Если нет, то как насчет пакетного файла Windows или аналогичного, который может это сделать?

Ответ 1

Если вы в первый раз --init репо, вам сначала нужно использовать --init:

git submodule update --init --recursive

Для git 1.8.2 или выше была добавлена опция --remote для поддержки обновления до последних подсказок удаленных веток:

git submodule update --recursive --remote

Это дает дополнительное преимущество, .gitmodules в уважении любых веток "не по умолчанию", указанных в .gitmodules или .git/config (если они у вас есть, по умолчанию это origin/master, и в этом случае некоторые другие ответы здесь будут работать как Что ж).

Для git 1.7.3 или выше вы можете использовать (но ниже приведены некоторые вопросы о том, какое обновление по-прежнему применяется):

git submodule update --recursive

или же:

git pull --recurse-submodules

если вы хотите вытащить свои подмодули к последним коммитам, на что указывает репо.

Смотрите git-submodule (1) для подробностей

Ответ 2

git pull --recurse-submodules --jobs=10

Git впервые узнал в 1.8.5.

В первый раз вам нужно запустить

git submodule update --init --recursive

Ответ 3

На init запускается следующая команда:

git submodule update --init --recursive

из каталога git repo лучше всего работает для меня.

Это потянет все последние, включая подмодули.

Разъяснения

git - the base command to perform any git command
    submodule - Inspects, updates and manages submodules.
        update - Update the registered submodules to match what the superproject
        expects by cloning missing submodules and updating the working tree of the
        submodules. The "updating" can be done in several ways depending on command
        line options and the value of submodule.<name>.update configuration variable.
            --init without the explicit init step if you do not intend to customize
            any submodule locations.
            --recursive is specified, this command will recurse into the registered
            submodules, and update any nested submodules within.

После этого вы можете просто запустить:

git submodule update --recursive

из каталога git repo лучше всего работает для меня.

Это будет тянуть все последние, включая подмодули.

Ответ 4

Примечание. Это с 2009 года, возможно, было хорошо, но теперь есть лучшие варианты.

Мы используем это. Он назывался git-pup:

#!/bin/bash
# Exists to fully update the git repo that you are sitting in...

git pull && git submodule init && git submodule update && git submodule status

Просто поместите его в соответствующий каталог bin (/usr/local/bin). Если в Windows вам может потребоваться изменить синтаксис, чтобы заставить его работать:)

Update:

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

Я уверен, что git не имеет для этого команды. Для этого вам нужно будет определить, что такое HEAD для субмодуля. Это может быть так же просто, как сказать, что master - самая современная ветка и т.д.

После этого создайте простой script, который выполняет следующие действия:

  • проверить git submodule status для "измененных" репозиториев. Это указывает первый символ выходных строк. Если подрепо будет изменено, вы НЕ захотите продолжить.
  • для каждого зарегистрированного репо, cd в его каталог и запустите git checkout master && git pull. Проверьте наличие ошибок.
  • В конце я предлагаю вам распечатать дисплей пользователю, чтобы указать текущий статус подмодулей - возможно, предложите им добавить все и совершить?

Я хотел бы упомянуть, что этот стиль на самом деле не был разработан для подмодулей git. Как правило, вы хотите сказать, что "LibraryX" находится в версии "2.32" и останется таким, пока я не скажу "обновить".

То есть, в некотором смысле, то, что вы делаете с описанным script, но просто более автоматически. Требуется помощь!

Обновление 2:

Если вы находитесь на платформе Windows, вам может понадобиться использовать Python для реализации script, поскольку он очень способен в этих областях. Если вы используете unix/linux, я предлагаю только bash script.

Нужны какие-либо разъяснения? Просто отправьте комментарий.

Ответ 5

Хенрик находится на правильном пути. Команда foreach может выполнять любую произвольную оболочку script. Возможны две возможности:

git submodule foreach git pull origin master

и

git submodule foreach /path/to/some/cool/script.sh

Это будет проходить через все инициализированные подмодули и запускать заданные команды.

Ответ 6

Следующие действия работали для меня в Windows.

git submodule init
git submodule update

Ответ 7

Edit

В комментариях было указано (philfreo), что требуется последняя версия. Если есть какие-либо вложенные подмодули, которые должны быть в их последней версии:

git submodule foreach --recursive git pull

----- Устаревший комментарий ниже -----

Разве это не официальный способ сделать это?

git submodule update --init

Я использую его каждый раз. На данный момент проблем нет.

Edit:

Я только что нашел, что вы можете использовать:

git submodule foreach --recursive git submodule update --init 

который также рекурсивно вытащит все подмодули, т.е. зависимости.

Ответ 8

Как может случиться так, что ветвь ваших подмодулей по умолчанию не master, вот как я могу автоматизировать обновление модулей Git:

git submodule init
git submodule update
git submodule foreach 'git fetch origin; git checkout $(git rev-parse --abbrev-ref HEAD); git reset --hard origin/$(git rev-parse --abbrev-ref HEAD); git submodule update --recursive; git clean -dfx'

Ответ 9

Первый раз

Подкомпоны клона и Init

git clone [email protected]:speedovation/kiwi-resources.git resources
git submodule init

Отдых

Во время разработки просто вытащите и обновите подмодуль

git pull --recurse-submodules  && git submodule update --recursive

Обновить подмодуль Git для последнего фиксации по происхождению

git submodule foreach git pull origin master

Предпочтительный путь должен быть ниже

git submodule update --remote --merge

Примечание: последние две команды имеют одинаковое поведение

Ответ 10

Я не знаю, с какой версии git это работает, но это то, что вы ищете:

git submodule update --recursive

Я использую его с git pull для обновления корневого репозитория:

git pull && git submodule update --recursive

Ответ 11

Приведенные выше ответы хороши, однако мы использовали git-hooks, чтобы сделать это проще, но получается, что в git 2.14 вы можете установить для git config submodule.recurse значение true, чтобы включить подмодули для обновляется, когда вы загружаете в свой репозиторий git.

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

Можно сделать с помощью:

git config submodule.recurse true

Ответ 13

Git для Windows 2.6.3:

git submodule update --rebase --remote

Ответ 14

Я сделал это, адаптировав gahooa ответ выше:

Интегрируйте его с помощью git [alias]...

Если ваш родительский проект имеет что-то вроде этого в .gitmodules:

[submodule "opt/submodules/solarized"]
    path = opt/submodules/solarized
    url = [email protected]:altercation/solarized.git
[submodule "opt/submodules/intellij-colors-solarized"]
    path = opt/submodules/intellij-colors-solarized
    url = [email protected]:jkaving/intellij-colors-solarized.git

Добавьте что-то подобное в свой .gitconfig

[alias]
    updatesubs = "!sh -c \"git submodule init && git submodule update && git submodule status\" "

Затем, чтобы обновить ваши подмодули, запустите:

git updatesubs

У меня есть пример в моем настройка настройки среды.

Ответ 15

С верхнего уровня в репо:

git submodule foreach git checkout develop
git submodule foreach git pull

Это переключит все ветки на разработку и загрузку последних

Ответ 16

Вот командная строка, которая вытаскивает из всех ваших репозиториев git, являются ли они или нет подмодулями:

ROOT=$(git rev-parse --show-toplevel 2> /dev/null)
find "$ROOT" -name .git -type d -execdir git pull -v ';'

Если вы запустите его в своем верхнем хранилище git, вы можете заменить "$ROOT" на ..

Ответ 17

Все, что вам нужно сделать сейчас, это простая git checkout

Просто убедитесь, что он git config --global submodule.recurse true помощью этой глобальной конфигурации: git config --global submodule.recurse true

Ответ 18

Думаю, вам нужно написать script, чтобы сделать это. Честно говоря, я мог бы установить python для этого, чтобы вы могли использовать os.walk to cd для каждого каталога и выдавать соответствующие команды. Использование python или другого языка сценариев, кроме пакета, позволит вам легко добавлять/удалять подпроекты без необходимости изменять script.

Ответ 19

Примечание: не слишком простой способ, но работоспособный, и у него есть свои уникальные профи.

Если вы хотите клонировать только ревизию репозитория HEAD и только HEAD всех своих подмодулей (т.е. для проверки "trunk" ), тогда можно использовать следующую Lua script. Иногда простая команда git submodule update --init --recursive --remote --no-fetch --depth=1 может привести к невосстановимой ошибке git. В этом случае необходимо вручную очистить подкаталог каталога .git/modules и подмодулировать клон с помощью команды git clone --separate-git-dir. Единственная сложность заключается в том, чтобы узнать URL-адрес каталога .git подмодуля и путь подмодуля в дереве суперпроектов.

Примечание: script проверяется только на репозитории https://github.com/boostorg/boost.git. Его особенности: все подмодули, размещенные на одном и том же хосте, и .gitmodules содержат только относительные URL-адреса.

-- mkdir boost ; cd boost ; lua ../git-submodules-clone-HEAD.lua https://github.com/boostorg/boost.git .
local module_url = arg[1] or 'https://github.com/boostorg/boost.git'
local module = arg[2] or module_url:match('.+/([_%d%a]+)%.git')
local branch = arg[3] or 'master'
function execute(command)
    print('# ' .. command)
    return os.execute(command)
end
-- execute('rm -rf ' .. module)
if not execute('git clone --single-branch --branch master --depth=1 ' .. module_url .. ' ' .. module) then
    io.stderr:write('can\'t clone repository from ' .. module_url .. ' to ' .. module .. '\n')
    return 1
end
-- cd $module ; git submodule update --init --recursive --remote --no-fetch --depth=1
execute('mkdir -p ' .. module .. '/.git/modules')
assert(io.input(module .. '/.gitmodules'))
local lines = {}
for line in io.lines() do
    table.insert(lines, line)
end
local submodule
local path
local submodule_url
for _, line in ipairs(lines) do
    local submodule_ = line:match('^%[submodule %"([_%d%a]-)%"%]$')
    if submodule_ then
        submodule = submodule_
        path = nil
        submodule_url = nil
    else
        local path_ = line:match('^%s*path = (.+)$')
        if path_ then
            path = path_
        else
            submodule_url = line:match('^%s*url = (.+)$')
        end
        if submodule and path and submodule_url then
            -- execute('rm -rf ' .. path)
            local git_dir = module .. '/.git/modules/' .. path:match('^.-/(.+)$')
            -- execute('rm -rf ' .. git_dir)
            execute('mkdir -p $(dirname "' .. git_dir .. '")')
            if not execute('git clone --depth=1 --single-branch --branch=' .. branch .. ' --separate-git-dir ' .. git_dir .. ' ' .. module_url .. '/' .. submodule_url .. ' ' .. module .. '/' .. path) then
                io.stderr:write('can\'t clone submodule ' .. submodule .. '\n')
                return 1
            end
            path = nil
            submodule_url = nil
        end
    end
end