我们使用git子模块来管理一些依赖于我们开发的许多其他库的大型项目。每个库都是一个单独的repo,作为子模块引入到依赖项目中。在开发过程中,我们经常想要获取每个依赖子模块的最新版本。
如何获取所有git子模块的最新更改?
我们使用git子模块来管理一些依赖于我们开发的许多其他库的大型项目。每个库都是一个单独的repo,作为子模块引入到依赖项目中。在开发过程中,我们经常想要获取每个依赖子模块的最新版本。
如何获取所有git子模块的最新更改?
当前回答
git pull --recurse-submodules --jobs=10
git在1.8.5中首次学习的特性。
在修复错误之前,第一次需要运行
git子模块更新--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'
如果是第一次签出回购,则需要使用--init first:
git submodule update --init --recursive
对于git1.8.2或更高版本,添加了选项--remote以支持更新到远程分支的最新提示:
git submodule update --recursive --remote
这还有一个额外的好处,那就是尊重.gitmodules或.git/config文件中指定的任何“非默认”分支(如果您碰巧有,默认值是origin/master,在这种情况下,这里的一些其他答案也会起作用)。
对于git 1.7.3或更高版本,您可以使用(但以下关于更新仍然适用的问题):
git submodule update --recursive
or:
git pull --recurse-submodules
如果您希望将子模块拉到最新的提交,而不是repo指向的当前提交。
详见git子模块(1)
正如antitoxic的回答所指出的,一个简单的git子模块foreach——递归git pull就足够了。
弗朗西斯·培根(Francis Bacon)的回答指出,git pull-递归子模块可能不同。
您可以使用详细选项进行测试并查看发生了什么:
git pull -v --recurse-submodules
但为此,您需要Git 2.40(2023年第1季度)。
“git pull-v--recurse submodule”(man)试图将-v传递给底层git submodule update(man),后者不理解请求并弹出:这已经用git 2.40(2023年第1季度)纠正。
参见Sven Strickroth(csware)提交的6f65f84(2022年12月10日)。(由Junio C Hamano--gitster--在提交b3b9e5c中合并,2022年12月28日)
子模块:接受更新命令的-v签字人:Sven Strickroth
由于a56771a(“builtin/pull:尊重子模块中的冗余设置”,2018-01-25,Git v2.17.0-rc0--批次#3中列出的merge),“Git pull-v--递归子模块”(man)将-v传播到子模块命令,但因为后者命令不理解该选项,所以它会退出。教“git子模块更新”(man)接受修复选项。
不再“barfing”(即显示用法'gitsubmodule foreach[-quiet][--recursive][--]<command>'),因为-v是gitsubmodule的未知选项。
备注:不太容易,但可行,它有自己独特的优点。
若要只克隆存储库的HEAD修订版和所有子模块的HEAD(即签出“trunk”),那个么可以使用以下Lua脚本。有时,简单的命令git submodule update--init--recursive--remote--no fetch--depth=1会导致不可恢复的git错误。在这种情况下,需要清理.git/modules目录的子目录,并使用gitclone--separate gitdir命令手动克隆子模块。唯一的复杂性是在超级项目树中查找子模块的URL、.git目录的路径和子模块的路径。
备注:脚本仅针对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
我想你必须写一个剧本才能做到这一点。老实说,我可能会安装python,这样您就可以使用os.walk来cd到每个目录并发出相应的命令。使用python或其他脚本语言(而不是批处理),可以轻松添加/删除子项目,而无需修改脚本。