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

1527

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

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

  • 0
    Git-Deep должен помочь с этим.
  • 3
    @Brad Вы хотите обновить свои копии подмодулей до коммитов оборотов, названных в главном проекте; или вы хотите получить последний коммит HEAD из каждого подмодуля? Большинство ответов здесь относятся к первым; многие хотят последнего.
Теги:
git-submodules

19 ответов

1869
Лучший ответ

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

git submodule update --recursive --remote

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

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

git submodule update --recursive

или

git pull --recurse-submodules

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

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

git submodule update --init --recursive

Для старше, git 1.6.1 или выше вы можете использовать что-то похожее (модифицированное для соответствия):

git submodule foreach git pull origin master

Подробнее см. git -submodule (1)

  • 0
    Отлично, это то, что мне было нужно. Обратите внимание, что при использовании msys-git в командной строке Windows вам нужно что-то более позднее, чем v1.5.6. Мне пришлось обновить до 1.6.3, чтобы заставить его работать. Еще раз спасибо.
  • 4
    Как говорится, вам нужно изменить выполненную команду в соответствии с вашими потребностями. Я настроил его так, чтобы получать все, что отслеживает текущая ветвь, и перебазировать его в текущую ветвь, что довольно удобно для настройки :)
Показать ещё 15 комментариев
612

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

git pull --recurse-submodules

функция git, впервые изученная в 1.7.3.

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

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

git submodule update --recursive --remote
  • 29
    проголосовал, я использую это: псевдоним update_submodules = 'git pull --recurse-submodules && git submodule update'
  • 3
    Это работает, если субмодули уже были извлечены хотя бы один раз, но для субмодулей, которые никогда не были извлечены, см. Ответ gahooa ниже.
Показать ещё 6 комментариев
321

При запуске 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, работает лучше всего для меня.

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

Разъяснения

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.
            any submodule locations.
            --recursive is specified, this command will recurse into the registered
            submodules, and update any nested submodules within.
  • 9
    Да, ответ с наибольшим количеством голосов был лучшим способом сделать это в '09, но теперь это определенно проще и интуитивно понятнее.
  • 2
    @MichaelScottCuthbert спасибо, я уверен, что через 3 года эта команда тоже будет сумасшедшей
Показать ещё 5 комментариев
316

Примечание. Это с 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.

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

  • 0
    Я не думаю, что это то, что я хочу. Разве это не вытянет версию подмодулей, с которой последний раз был завершен супер-проект? Я хочу вытащить головную версию всех подмодулей.
  • 3
    Это прекрасно работает и работает не только для обновления подмодулей, но и для их извлечения в первый раз, если это то, что вам нужно.
Показать ещё 4 комментария
146

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

git submodule foreach git pull origin master

и

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

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

141

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

git submodule init
git submodule update
  • 5
    Это явно не то, о чем просил ОП. Он будет обновляться только до соответствующей фиксации субмодуля, а не до последней.
  • 52
    Это, однако, единственное, что на этой странице заставило Git вытащить субмодули, когда я впервые проверил репо
Показать ещё 1 комментарий
34

Edit

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

git submodule foreach --recursive git pull

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

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

git submodule update --init

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

Edit:

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

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

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

  • 5
    Ваш ответ не отвечает на вопрос ОП, но чтобы сделать то, что вы предложили, вы можете просто сказать: git submodule update --init --recursive
  • 2
    Понятно, нужна последняя версия. Что ж, это может быть полезно, если есть вложенные подмодули: git submodule foreach --recursive git pull
Показать ещё 1 комментарий
32

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

Первый раз

Подкомпоны клона и 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

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

  • 0
    Я сделал git-клон без подмодулей по ошибке, и все остальные опции не сработали, никто не делал клоны подмодулей. Используя ваше, git submodule update сделало свое дело. Теперь я загружаю данные субмодуля, отсутствующие в первом шаге клона. Спасибо. Я не очень хорош в мерзавце: C
  • 0
    Этот ансер на самом деле является очень хорошим ответом, чтобы задать вопрос здесь: почему я должен "... --recursive-submodules ..", а затем дополнительно "... update ..." и даже ".. .foreach ... "позже, чтобы получить последний коммит? Все это не похоже на GIT! Что делает «обновление» и почему я должен вручную переходить на каждый модуль, чтобы вытащить? Разве это не то, что делает "... --recurse-submodules .."? Есть намеки?
18

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

git submodule update --recursive

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

git pull && git submodule update --recursive
6

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

  • 2
    На данный момент это не реализовано в git 1.7.1.
  • 0
    это определенно будет полезно, если в конечном итоге будет принято.
4

Git для Windows 2.6.3:

git submodule update --rebase --remote

  • 0
    Это единственный, который работал на меня. Я даже не смог запустить или обновить, так как указатель субмодуля указывал на версию, которой больше не было в пульте
3

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

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

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

git config submodule.recurse true
3

Я сделал это, адаптировав 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

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

2

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

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

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

1

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

Если вы хотите клонировать только ревизию репозитория 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
1

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

0

С верхнего уровня в репо: подмодуль git foreach git checkout разработать подмодуль git foreach git pull

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

  • 0
    У меня не работает, с git 2.7.
  • 0
    У вас есть что-то вроде файла Everything sln, который добавляет все ссылки на проекты в дереве? И какую ошибку вы видите? Можете ли вы проверить свой файл gitignore тоже
0

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

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

Ещё вопросы

Сообщество Overcoder
Наверх
Меню