我们正在使用 git 子模块来管理几个依赖于我们开发的许多其他库的大型项目。每个库都是一个单独的存储库,作为子模块引入依赖项目。在开发过程中,我们经常想去获取每个依赖子模块的最新版本。
git 是否有内置命令来执行此操作?如果不是,那么可以使用 Windows 批处理文件或类似文件怎么样?
我们正在使用 git 子模块来管理几个依赖于我们开发的许多其他库的大型项目。每个库都是一个单独的存储库,作为子模块引入依赖项目。在开发过程中,我们经常想去获取每个依赖子模块的最新版本。
git 是否有内置命令来执行此操作?如果不是,那么可以使用 Windows 批处理文件或类似文件怎么样?
如果这是您第一次签出回购协议,您需要先使用--init
:
git submodule update --init --recursive
对于git 1.8.2或更高版本,--remote
添加了支持更新到远程分支最新提示的选项:
git submodule update --recursive --remote
.gitmodules
这具有尊重or文件中指定的任何“非默认”分支的额外好处.git/config
(如果您碰巧有任何分支,默认是 origin/master,在这种情况下,这里的一些其他答案也可以使用)。
对于git 1.7.3或更高版本,您可以使用(但以下关于更新仍然适用的问题):
git submodule update --recursive
或者:
git pull --recurse-submodules
如果您想将您的子模块拉到最新提交而不是当前提交,则 repo 指向。
详见git-submodule(1 )
git pull --recurse-submodules --jobs=10
git 在 1.8.5 中首次学习的功能。
在错误修复之前,您第一次确实需要运行
git 子模块更新 --init --recursive
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 上,您可能需要修改语法以使其正常工作:)
更新:
作为对原作者关于拉入所有子模块的所有 HEAD 的评论的回应——这是一个很好的问题。
我很确定git
内部没有此命令。为此,您需要确定子模块的 HEAD 到底是什么。这可能就像说master
是最新的分支一样简单,等等......
在此之后,创建一个执行以下操作的简单脚本:
git submodule status
“修改过的”存储库。输出行的第一个字符表明了这一点。如果修改了子存储库,您可能不想继续。git checkout master && git pull
. 检查错误。我想提一下,这种风格并不是 git 子模块的真正设计目的。通常,您想说“LibraryX”的版本是“2.32”,并且会一直保持这种状态,直到我告诉它“升级”。
也就是说,从某种意义上说,您使用所描述的脚本正在做什么,但只是更自动。需要呵护!
更新 2:
如果你在 Windows 平台上,你可能想看看使用 Python 来实现脚本,因为它在这些领域非常有能力。如果您使用的是 unix/linux,那么我建议您只使用 bash 脚本。
需要任何说明吗?只需发表评论。
亨里克走在正确的轨道上。'foreach' 命令可以执行任意的 shell 脚本。提取最新版本的两个选项可能是,
git submodule foreach git pull origin master
和,
git submodule foreach /path/to/some/cool/script.sh
这将遍历所有初始化的子模块并运行给定的命令。
以下内容在 Windows 上对我有用。
git submodule init
git submodule update
克隆和初始化子模块
git clone git@github.com: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
注意:最后两个命令具有相同的行为
由于您的子模块的默认分支可能是not 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'
编辑:
在评论中指出(由philfreo)需要最新版本。如果有任何嵌套子模块需要在其最新版本中:
git submodule foreach --recursive git pull
-----下面的过时评论-----
这不是官方的做法吗?
git submodule update --init
我每次都用它。到目前为止没有问题。
编辑:
我刚刚发现你可以使用:
git submodule foreach --recursive git submodule update --init
这也将递归地提取所有子模块,即依赖项。
我不知道这是哪个版本的 git,但这就是您要搜索的内容:
git submodule update --recursive
我也用它git pull
来更新根存储库:
git pull && git submodule update --recursive
对我来说,git 2.24.03,更新到 .gitmoodule 中定义的远程分支的最新提交。
git submodule update --recursive --init
git submodule update --recursive --remote
git 版本 2.24.3 (Apple Git-128)
请注意:
有人说这
git pull --recurse-submodules
与git submodule update --recursive --remote
. 但从我的测试来看,git pull --recurse-submodules
可能不会更新到 .gitmoodule 中定义的远程分支的最新提交。
上面的答案很好,但是我们使用 git-hooks 使这更容易,但事实证明,在git 2.14中,您可以设置git config submodule.recurse
为 true 以使子模块在您拉入 git 存储库时更新。
如果它们在分支上,这将产生推动所有子模块更改的副作用,但是如果您已经需要这种行为,这可以完成这项工作。
可以通过使用来完成:
git config submodule.recurse true
我经常使用这个命令,到目前为止它有效。
git pull
git submodule foreach --recursive git checkout master
git submodule foreach --recursive git pull
希望这更快。
适用于 Windows 2.6.3的 Git :
git submodule update --rebase --remote
根据从远程提取每个子模块的“最新”代码的现有答案来澄清一些事情。
如果“ latest ”表示签入的子模块指针,那么一定要使用:
git submodule update --recursive
- or -
git pull --recurse-submodules --jobs=X
如果“最新”意味着最新的main,那么这样的事情可以工作:
git submodule foreach "git checkout main && git pull"
不幸的是,这意味着没有“--jobs”选项,所以我们不能并行运行它。我见过的最接近并行运行的方法是使用pfs python 代码。
从 repo 的顶层:
git submodule foreach git checkout develop
git submodule foreach git pull
这将切换所有分支以开发和拉最新
将其与 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
我的环境设置 repo中有一个示例。
您现在需要做的只是一个简单的git checkout
只需确保通过此全局配置启用它:git config --global submodule.recurse true
这是从所有 git 存储库中提取的命令行,无论它们是否是子模块:
ROOT=$(git rev-parse --show-toplevel 2> /dev/null)
find "$ROOT" -name .git -type d -execdir git pull -v ';'
如果您在顶级 git 存储库中运行它,则可以将其替换"$ROOT"
为.
.
备注:不是太简单的方法,但可行,它有自己独特的优点。
如果只想克隆HEAD
存储库的修订版和HEAD
所有子模块的 s(即检查“主干”),则可以使用以下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。
-- 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
tocd
每个目录并发出适当的命令。使用 python 或其他脚本语言(批处理除外)可以让您轻松添加/删除子项目,而无需修改脚本。