我们使用git子模块来管理一些依赖于我们开发的许多其他库的大型项目。每个库都是一个单独的repo,作为子模块引入到依赖项目中。在开发过程中,我们经常想要获取每个依赖子模块的最新版本。
如何获取所有git子模块的最新更改?
我们使用git子模块来管理一些依赖于我们开发的许多其他库的大型项目。每个库都是一个单独的repo,作为子模块引入到依赖项目中。在开发过程中,我们经常想要获取每个依赖子模块的最新版本。
如何获取所有git子模块的最新更改?
当前回答
对我来说,git2.24.03,更新到.gitmodules中定义的远程分支的最新提交。
git子模块更新--递归--init
git子模块更新--递归--远程
git版本2.24.3(Apple git-128)
请注意:有人说过git pull-递归子模块与git子模块update-递归-远程相同。但根据我的测试,gitpull-recurse子模块可能不会更新为.gitmodules中定义的远程分支的最新提交。
其他回答
备注:不太容易,但可行,它有自己独特的优点。
若要只克隆存储库的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
上面的答案很好,不过我们使用了git钩子来简化这一过程,但事实证明,在git2.14中,您可以将git-config子模块.recure设置为true,以便在您拉到git存储库时更新子模块。
如果所有子模块都在分支上,这会产生一个副作用,即推动所有子模块的更改,但如果您已经需要这种行为,这可以完成任务。
可通过以下方式完成:
git config submodule.recurse true
我编写了这个简单的shell脚本,对我来说很好。
#!/bin/bash
#git init
git init
#git clone repo including submodules
git clone --recurse-submodules https://github.com/username/project.git
#change directory -repo
cd project
#update the remote ie tag/commits
git submodule update --remote
#add commit
git commit -a -m "commit in submodule"
#git push
git push -u origin
根据从远程获取每个子模块的“最新”代码的现有答案,澄清一些问题。
如果“最新”是指签入的子模块指针,则无论如何使用:
git submodule update --recursive
- or -
git pull --recurse-submodules --jobs=X
如果“最新”是指main的最新版本,那么类似这样的内容可以起作用:
git submodule foreach "git checkout main && git pull"
不幸的是,这意味着没有“--jobs”选项,因此我们无法并行运行它。我所看到的最接近并行运行的方法是使用pfs-python代码。
以下内容在Windows上适用。
git submodule init
git submodule update