Простой способ получить последнюю версию всех подмодулей git

StackOverflow https://stackoverflow.com/questions/1030169

  •  06-07-2019
  •  | 
  •  

Вопрос

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

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

Это было полезно?

Решение

Если это в первый раз вы оформляете заказ на репозиторий, который вам нужно использовать --init Первый:

git submodule update --init --recursive

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

git submodule update --recursive --remote

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

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

git submodule update --recursive

или:

git pull --recurse-submodules

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

Видишь git-подмодуль (1) для получения подробной информации

Другие советы

Если вам нужно вытащить материал для субмодулей в свои репозитории, используйте

git pull --recurse-submodules
  

Git, впервые изученный в 1.7.3.

Но это не будет проверять правильные коммиты (те, на которые указывает ваш главный репозиторий) в подмодулях

Чтобы проверить правильность фиксации в ваших подмодулях, вы должны обновить их после извлечения с помощью

git submodule update --recursive --remote

В 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, лучше всего подходит для меня.

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

Примечание:Это было в 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, вам, возможно, потребуется изменить синтаксис, чтобы заставить его работать :)

Обновить:

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

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

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

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

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

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

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

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

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

Хенрик на правильном пути.Команда 'foreach' может выполнить любой произвольный сценарий командной оболочки.Двумя вариантами извлечения самой последней версии могут быть,

git submodule foreach git pull origin master

и,

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

Это приведет к повторению всех инициализированный подмодули и выполняйте заданные команды.

В Windows мне помогло следующее.

git submodule init
git submodule update

Редактировать:

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

git submodule foreach --recursive git pull

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

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

git submodule update --init

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

Редактировать:

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

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

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

Так как может случиться, что веткой по умолчанию ваших подмодулей является не 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'

Первый раз

Подмодуль клонирования и инициализации

git clone git@github.com: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

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

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

git submodule update --recursive

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

git pull && git submodule update --recursive

Посмотрите на http://lists.zerezo.com/git/msg674976.html который вводит параметр --track

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

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

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

git config submodule.recurse true

Git для Windows 2.6.3 :

обновление подмодуля git --rebase --remote

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

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

Если у вашего родительского проекта есть что-то подобное в .gitmodules :

[submodule "opt/submodules/solarized"]
    path = opt/submodules/solarized
    url = git@github.com:altercation/solarized.git
[submodule "opt/submodules/intellij-colors-solarized"]
    path = opt/submodules/intellij-colors-solarized
    url = git@github.com:jkaving/intellij-colors-solarized.git

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

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

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

git updatesubs

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

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

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

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

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

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

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

git submodule foreach git checkout develop
git submodule foreach git pull

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

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

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

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

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

-- 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
Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top