简单的方法来拉最新的所有git submodules

我们使用git子模块来pipe理一些依赖于我们开发的其他库的大型项目。 每个图书馆都是一个单独的回购作为一个子模块进入依赖项目。 在开发过程中,我们经常想要抓住每个从属子模块的最新版本。

git是否有一个内置的命令来做到这一点? 如果没有,那么Windowsbatch file或类似的可以做到这一点呢?

对于git 1.8.2或更高--remote ,添加了--remote选项来支持更新远程分支的最新技巧:

 git submodule update --recursive --remote 

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

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

 git submodule update --recursive 

要么:

 git pull --recurse-submodules 

如果你想拉你的submodules到最新的承诺intead的回购指向。

注意:如果这是您第一次签出回购,您需要使用--init优先:

 git submodule update --init --recursive 

对于更老的git 1.6.1或更高版本,您可以使用类似的东西(修改为适合):

 git submodule foreach git pull origin master 

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

如果您需要将子模块的东西放入您的子模块存储库,请使用

 git pull --recurse-submodules 

在1.7.3中首先学习了一个特性git。

但是这不会在子模块中检出正确的提交(你的主存储库指向的提交)

要检出您的子模块中的正确提交,您应该在使用后更新它们

 git submodule update --recursive --remote 

注:这是从2009年开始,可能已经很好,但现在有更好的select。

我们用这个。 它被称为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在内部没有这个命令。 为了做到这一点,您需要确定子模块的真正用途。 这可能就像说master是最新的分支等一样简单。

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

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

我想提一下,这个风格并不是真正的git子模块。 通常情况下,你想说“LibraryX”是在版本“2.32”,并保持这种方式,直到我告诉它“升级”。

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

更新2:

如果你在一个Windows平台上,你可能想看看使用Python来实现这个脚本,因为它在这些领域非常有能力。 如果你在Unix / Linux上,那么我build议只是一个bash脚本。

需要任何澄清? 只是发表评论。

运行命令:

 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. 

Henrik在正确的轨道上。 'foreach'命令可以执行任意的shell脚本。 两种select最新的可能是,

 git submodule foreach git pull origin master 

和,

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

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

以下在Windows上为我工作。

 git submodule init git submodule update 

编辑

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

 git submodule foreach --recursive git pull 

—–以下过时的评论—–

这不是官方的做法吗?

 git submodule update --init 

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

编辑:

我刚刚发现你可以使用:

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

哪个也会recursion地拉取所有的子模块,即依赖关系。

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

第一次

克隆和初始化子模块

 git clone git@github.com:speedovation/kiwi-resources.git resources git submodule init 

rest

在开发过程中,只需拉和更新子模块

 git pull --recurse-submodules && git submodule update --recursive 

将Git子模块更新为最新的原始提交

 git submodule foreach git pull origin master 

首选的方式应该在下面

 git submodule update --remote --merge 

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

我不知道从哪个版本的git这是工作,但这就是你正在寻找的:

 git submodule update --recursive 

我用它与git pull来更新根存储库:

 git pull && git submodule update --recursive 

请参阅http://lists.zerezo.com/git/msg674976.html ,其中介绍了–track参数

Git for windows 2.6.3

git submodule update --rebase --remote

我通过修改gahooa的答案来做到这一点:

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

我在我的环境设置回购中有一个例子 。

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

如果只想克隆版本库的HEAD版本,并且只克隆其所有子模块的HEAD (即签出“trunk”),那么可以使用以下的Lua脚本。 有时简单的命令git submodule update --init --recursive --remote --no-fetch --depth=1可能会导致不可恢复的git错误。 在这种情况下,需要使用git clone --separate-git-dir命令手动清理.git/modules目录的子目录并克隆子模块。 唯一的复杂性是在超级项目树中查找URL ,子模块的.git目录path和子模块path。

备注:脚本仅在https://github.com/boostorg/boost.git存储库中进行testing。 它的特点是:在同一主机上托pipe的所有子模块和.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仓库中取出的命令行,无论它们是否是子模块:

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

如果你在顶级的git仓库中运行它,你可以把"$ROOT"replace成.

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