Мы используем подмодули git для управления парой крупных проектов, которые зависят от многих других библиотек, которые мы разработали. Каждая библиотека представляет собой отдельный репозиторий, внесенный в зависимый проект в виде подмодуля. Во время разработки мы часто хотим просто взять последнюю версию каждого зависимого подмодуля.
Есть ли в git встроенная команда для этого? Если нет, то как насчет пакетного файла Windows или аналогичного, который может это сделать?
Для поддержки 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)
Если вам нужно вытащить материал для подмодулей в свои хранилища подмодулей, используйте
git pull --recurse-submodules
функция git, впервые изученная в 1.7.3.
Но это не будет проверять правильные коммиты (те, на которые указывает ваш основной репозиторий) в подмодулях
Чтобы проверить правильность коммитов в ваших подмодулях, вы должны обновить их после вытягивания с помощью
git submodule update --recursive --remote
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.
Примечание. Это с 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
для "измененных" репозиториев. Это указывает первый символ выходных строк. Если подрепо будет изменено, вы НЕ захотите продолжить.git checkout master && git pull
. Проверьте наличие ошибок.Я хотел бы упомянуть, что этот стиль на самом деле не был разработан для подмодулей git. Как правило, вы хотите сказать, что "LibraryX" находится в версии "2.32" и останется таким, пока я не скажу "обновить".
То есть, в некотором смысле, то, что вы делаете с описанным script, но просто более автоматически. Требуется помощь!
Обновление 2:
Если вы находитесь на платформе Windows, вам может понадобиться использовать Python для реализации script, поскольку он очень способен в этих областях. Если вы используете unix/linux, я предлагаю только bash script.
Нужны какие-либо разъяснения? Просто отправьте комментарий.
Хенрик находится на правильном пути. Команда foreach может выполнять любую произвольную оболочку script. Возможны две возможности:
git submodule foreach git pull origin master
и
git submodule foreach /path/to/some/cool/script.sh
Это будет проходить через все инициализированные подмодули и запускать заданные команды.
Следующие действия работали для меня в Windows.
git submodule init
git submodule update
Edit
В комментариях было указано (philfreo), что требуется последняя версия. Если есть какие-либо вложенные подмодули, которые должны быть в их последней версии:
git submodule foreach --recursive git pull
----- Устаревший комментарий ниже -----
Разве это не официальный способ сделать это?
git submodule update --init
Я использую его каждый раз. На данный момент проблем нет.
Edit:
Я только что нашел, что вы можете использовать:
git submodule foreach --recursive git submodule update --init
который также рекурсивно вытащит все подмодули, т.е. зависимости.
git submodule update --init --recursive
git submodule foreach --recursive git pull
Как может случиться так, что ветвь ваших подмодулей по умолчанию не 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'
Подкомпоны клона и Init
git clone [email protected]:speedovation/kiwi-resources.git resources
git submodule init
Во время разработки просто вытащите и обновите подмодуль
git pull --recurse-submodules && git submodule update --recursive
git submodule foreach git pull origin master
git submodule update --remote --merge
Примечание: последние две команды имеют одинаковое поведение
git submodule update
сделало свое дело. Теперь я загружаю данные субмодуля, отсутствующие в первом шаге клона. Спасибо. Я не очень хорош в мерзавце: C
Я не знаю, с какой версии git это работает, но это то, что вы ищете:
git submodule update --recursive
Я использую его с git pull
для обновления корневого репозитория:
git pull && git submodule update --recursive
Посмотрите http://lists.zerezo.com/git/msg674976.html, в котором вводится параметр -track
Git для Windows 2.6.3:
git submodule update --rebase --remote
Вышеприведенные ответы хороши, однако мы использовали git-hooks, чтобы упростить это, но оказалось, что в git 2.14 вы можете установить git config submodule.recurse
в значение true, чтобы позволить подмодулям обновляться при извлечении из вашего хранилища git.
Это будет иметь побочный эффект, когда вы будете подталкивать все подмодули, которые у вас есть, если они находятся на ветках, но если вам уже нужно такое поведение, это может помочь.
Может быть сделано с помощью:
git config submodule.recurse true
Я сделал это, адаптировав 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
У меня есть пример в моем настройка настройки среды.
Вот командная строка, которая вытаскивает из всех ваших репозиториев git, являются ли они или нет подмодулями:
ROOT=$(git rev-parse --show-toplevel 2> /dev/null)
find "$ROOT" -name .git -type d -execdir git pull -v ';'
Если вы запустите его в своем верхнем хранилище git, вы можете заменить "$ROOT"
на .
.
Примечание: не слишком простой способ, но работоспособный, и у него есть свои уникальные профи.
Если вы хотите клонировать только ревизию репозитория 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
Думаю, вам нужно написать script, чтобы сделать это. Честно говоря, я мог бы установить python для этого, чтобы вы могли использовать os.walk
to cd
для каждого каталога и выдавать соответствующие команды. Использование python или другого языка сценариев, кроме пакета, позволит вам легко добавлять/удалять подпроекты без необходимости изменять script.
С верхнего уровня в репо: подмодуль git foreach git checkout разработать подмодуль git foreach git pull
Это переключит все ветки на разработку и загрузку последних
Все, что вам нужно сделать сейчас, это простая git checkout
Просто убедитесь, что он git config --global submodule.recurse true
помощью этой глобальной конфигурации: git config --global submodule.recurse true