轻松获取最新的git子模块

问题描述 投票:1601回答:19

我们使用git子模块来管理一些依赖于我们开发的许多其他库的大型项目。每个库都是作为子模块引入依赖项目的单独repo。在开发过程中,我们经常想要抓住每个依赖子模块的最新版本。

git有内置命令来执行此操作吗?如果没有,Windows批处理文件或类似文件怎么样呢?

git git-submodules
19个回答
2212
投票

如果这是你第一次结账回购,你需要先使用--init

git submodule update --init --recursive

对于git 1.8.2或更高版本,添加了选项--remote以支持更新远程分支的最新提示:

git submodule update --recursive --remote

这有额外的好处是尊重.gitmodules.git/config文件中指定的任何“非默认”分支(如果你碰巧有任何,默认是origin / master,在这种情况下,其他一些答案也适用)。

对于git 1.7.3或更高版本,你可以使用(但下面有关于更新仍然适用的问题):

git submodule update --recursive

要么:

git pull --recurse-submodules

如果你想将你的子模块拉到最新的提交而不是repo指向的。

有关详细信息,请参阅git-submodule(1)


18
投票

我不知道从哪个版本的git开始工作,但这就是你要搜索的内容:

git submodule update --recursive

我和git pull一起使用它来更新根存储库:

git pull && git submodule update --recursive

6
投票

看看介绍--track参数的http://lists.zerezo.com/git/msg674976.html


6
投票

上面的答案是好的,但我们使用git-hooks使这更容易,但事实证明,在git 2.14中,您可以将git config submodule.recurse设置为true以使子模块在您拉到git存储库时更新。

如果它们在分支上,这会产生推动所有子模块改变的副作用,但如果你需要这种行为已经可以完成这项工作。

可以通过使用:

git config submodule.recurse true

4
投票

适用于Windows 2.6.3的Git:

git submodule update --rebase --remote


3
投票

我通过改编gahooaanswer above来做到这一点:

将它与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

我在我的example有一个environment setup repo


2
投票

这是从所有git存储库中提取的命令行,无论它们是否是子模块:

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

如果你在你的顶级git存储库中运行它,你可以将"$ROOT"替换为.


2
投票

你现在需要做的只是一个简单的git checkout

只需确保通过此全局配置启用它:git config --global submodule.recurse true


2
投票

从回购的顶层:

git submodule foreach git checkout develop
git submodule foreach git pull

这将切换所有分支以开发和拉取最新


1
投票

我想你必须写一个脚本才能做到这一点。说实话,我可能会安装python来执行它,以便您可以使用os.walkcd到每个目录并发出相应的命令。除了批处理之外,使用python或其他一些脚本语言将允许您轻松添加/删除子项目而无需修改脚本。


1
投票

备注:不是太容易,但可行,它有自己独特的优点。

如果想要仅克隆存储库的HEAD修订版并且仅克隆其所有子模块的HEADs(即结帐“trunk”),则可以使用以下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

609
投票
git pull --recurse-submodules --jobs 10

一个功能git首先在1.7.3中学到了。


370
投票

在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目录中,最适合我。

这将拉出所有最新的包括子模块。


302
投票

注意:这是从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是最新的分支等一样简单......

在此之后,创建一个执行以下操作的简单脚本:

  1. 检查git submodule status的“修改”存储库。输出行的第一个字符表示这一点。如果修改了子仓库,您可能不想继续。
  2. 对于列出的每个仓库,cd进入它的目录并运行git checkout master && git pull。检查错误。
  3. 最后,我建议你打印一个显示给用户,以指示子模块的当前状态 - 也许提示他们添加all并提交?

我想提一下,这种风格并不是git子模块的设计用途。通常情况下,您想说“LibraryX”的版本为“2.32”并保持这种状态,直到我告诉它“升级”。

也就是说,从某种意义上说,你正在用所描述的脚本做什么,但更自动。需要护理!

更新2:

如果您使用的是Windows平台,则可能需要使用Python来实现脚本,因为它在这些方面非常强大。如果您使用的是unix / linux,那么我建议只使用一个bash脚本。

需要澄清吗?刚发表评论。


155
投票

亨里克走在正确的轨道上。 'foreach'命令可以执行任何任意shell脚本。拉最新的两种选择可能是,

git submodule foreach git pull origin master

和,

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

这将迭代所有初始化的子模块并运行给定的命令。


142
投票

以下在Windows上为我工作。

git submodule init
git submodule update

33
投票

编辑:

在评论中指出(philfreo)需要最新版本。如果有任何嵌套子模块需要在其最新版本中:

git submodule foreach --recursive git pull

-----下面的过时评论-----

这不是官方的做法吗?

git submodule update --init

我每次都用它。到目前为止没问题。

编辑:

我发现你可以使用:

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

这也将递归地拉出所有子模块,即依赖项。


31
投票

由于可能发生子模块的默认分支不是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'

25
投票

第一次

克隆和初始化子模块

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

Preferred way should be below

git submodule update --remote --merge

注意:最后两个命令具有相同的行为

© www.soinside.com 2019 - 2024. All rights reserved.