Pergunta

Estamos usando submódulos git para gerenciar um par de grandes projetos que dependem de muitas outras bibliotecas que desenvolvemos. Cada biblioteca é um repo separado trazidos para o projeto dependente como um sub-módulo. Durante o desenvolvimento, que muitas vezes querem apenas ir pegar a versão mais recente de cada sub-módulo dependente.

Git tem construído em um comando para fazer isso? Se não, como sobre um arquivo de lote do Windows ou similar que pode fazê-lo?

Foi útil?

Solução

Se é pela primeira vez você check-out um repo que você precisa para uso --init primeiro:

git submodule update --init --recursive

Para git 1.8.2 ou acima do --remote opção foi adicionada para atualizar suporte para mais dicas de filiais remotas:

git submodule update --recursive --remote

Este tem a vantagem de respeitar quaisquer ramos "não padrão" especificados nos arquivos .gitmodules ou .git/config (se acontecer de você ter qualquer, o padrão é origin / master, caso em que algumas das outras respostas aqui iria funcionar tão bem ).

Para git 1.7.3 ou acima, você pode usar (mas o abaixo armadilhas em torno do que atualização não ainda se aplicam):

git submodule update --recursive

ou

git pull --recurse-submodules

Se você quer puxar seus submódulos os últimos commits intead do que os pontos de reporte para.

git-submódulo (1) para mais detalhes

Outras dicas

Se você precisa de coisas puxar para submódulos em seus repositórios submódulo usar

git pull --recurse-submodules

um git recurso aprendeu pela primeira vez em 1.7.3.

Mas isso vai se compromete a não verificação adequados (os seus repositório principal aponta para) em submódulos

Para conferir commits adequadas em seus submódulos você deve atualizá-los depois de puxar usando

git submodule update --recursive --remote

Na inicialização executando o seguinte comando:

git submodule update --init --recursive

de dentro do diretório repo git, funciona melhor para mim.

Isso vai puxar todos os mais recentes, incluindo sub-módulos.

Explicou

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.

Após isso, você pode simplesmente executar:

git submodule update --recursive

de dentro do diretório repo git, funciona melhor para mim.

Isso vai puxar todos os mais recentes, incluindo sub-módulos.

Nota:. Esta é a partir de 2009 e pode ter sido bom, então, mas há melhores opções agora

Nós usamos isso. É chamado 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

Basta colocá-lo em um diretório bin adequado (/ usr / / bin local). Se no Windows, pode ser necessário modificar a sintaxe para fazê-lo funcionar:)

Update:

Em resposta ao comentário pelo autor original sobre puxar em todas as cabeças de todos os submódulos -. Essa é uma boa pergunta

Eu tenho quase certeza que git não tem um comando para isso internamente. A fim de fazer isso, você precisa identificar o que CABEÇA é realmente para um sub-módulo. Isso poderia ser tão simples como dizer master é a mais até a filial data, etc ...

Em seguida, criar um script simples que faz o seguinte:

  1. git submodule status cheque de repositórios "modificados". O primeiro caractere das linhas de saída indica isso. Se um sub-repo é modificado, você pode não querer prosseguir.
  2. para cada repo listado, cd para ele do diretório e execute git checkout master && git pull. Verifique se há erros.
  3. No final, eu sugiro que você imprimir uma tela para o usuário para indicar o estado actual dos submódulos -? Talvez levá-los para adicionar todos e comprometer

Eu gostaria de mencionar que este estilo não é realmente o que submódulos git foram projetados para. Normalmente, você quer dizer "LibraryX" está na versão "2.32" e vai ficar assim até que eu diga a ele para "upgrade".

Isto é, em certo sentido, o que está fazendo com o roteiro descrito, mas apenas mais automaticamente. Cuidado é necessário!

Update 2:

Se você estiver em uma plataforma Windows, você pode querer olhar usando Python para implementar o script, pois é muito capaz nessas áreas. Se você estiver em Unix / Linux, então eu sugiro que apenas um script bash.

Precisa de quaisquer esclarecimentos? Basta postar um comentário.

Henrik está no caminho certo. O comando 'foreach' pode executar qualquer script shell arbitrários. Duas opções para puxar o mais recente pode ser,

git submodule foreach git pull origin master

e,

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

Isso vai percorrer todos inicializado submódulos e executar os comandos dados.

A seguir trabalhou para mim no Windows.

git submodule init
git submodule update

Editar :

Nos comentários foi apontado (por philfreo ) que a versão mais recente é necessária. Se não houver nenhum submódulos aninhados que precisam estar em sua versão mais recente:

git submodule foreach --recursive git pull

----- comentário desatualizado abaixo -----

Não é esta a maneira oficial de fazê-lo?

git submodule update --init

Eu usá-lo o tempo todo. Sem problemas até agora.

Editar:

Eu só descobri que você pode usar:

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

O que também irá recursivamente puxar todos os submódulos, ou seja, dependências.

Como pode acontecer que o ramo padrão de seus submódulos é não master, é assim que eu automatizar atualizações do Git completa submódulos:

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'

Primeira vez

Clone e Init Submódulo

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

Resto

Durante o desenvolvimento só puxar e atualização submodule

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

Atualização Git submódulo a mais recente comprometer em origem

git submodule foreach git pull origin master

forma preferida deve ser inferior

git submodule update --remote --merge

Nota: últimos dois comandos têm o mesmo comportamento

Eu não sei desde que versão do git isso está funcionando, mas é o que você está procurando:

git submodule update --recursive

Eu usá-lo com git pull para atualizar o repositório de raiz, também:

git pull && git submodule update --recursive

http://lists.zerezo.com/git/msg674976.html que introduz um --track parâmetro

As respostas acima são boas, no entanto, estavam usando git-ganchos para tornar isso mais fácil, mas verifica-se que em git 2,14 , você pode definir git config submodule.recurse como true para ativar submódulos para a atualizados quando você puxa para o seu repositório git.

Isto terá o efeito colateral de empurrar todos os submódulos mudar você tem, se eles estão em ramos no entanto, mas se você tiver necessidade de que o comportamento já este poderia fazer o trabalho.

Pode ser feito usando-se:

git config submodule.recurse true

Git para Windows 2.6.3 :

git submodule update --rebase --remote

Eu fiz isso através da adaptação gahooa 's resposta acima :

integrá-lo com um git [alias] ...

Se o seu projeto pai tem algo como isso em .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

Adicionar algo como isto dentro de sua .gitconfig

[alias]
    updatesubs = "!sh -c \"git submodule init && git submodule update && git submodule status\" "

Em seguida, atualizar seus submódulos, execute:

git updatesubs

Eu tenho um exemplo dele em meu ambiente configuração repo .

Aqui está a linha de comando para puxar de todos os seus repositórios git se eles são ou não submódulos:

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

Se você executá-lo em seu topo repositório git, você pode substituir "$ROOT" em ..

Tudo que você precisa fazer agora é um simples git checkout

Apenas certifique-se para habilitá-lo através desta configuração global: git config --global submodule.recurse true

A partir do nível superior no repo:

git submodule foreach git checkout develop
git submodule foreach git pull

Isso vai mudar todos os ramos para desenvolver e puxar mais recente

Eu acho que você vai ter que escrever um script para fazer isso. Para ser honesto, eu poderia instalar python para fazê-lo de modo que você pode usar os.walk para cd para cada diretório e emitir os comandos apropriados. Usando python ou alguma outra linguagem de script, além de lotes, que permitem que você adicione facilmente / subprojetos remove sem ter que modificar o script.

Observação:. Não muito fácil assim, mas viável e tem suas próprias vantagens únicas

Se alguém quiser clone única revisão HEAD de um repositório e apenas HEADs de todos os seus sub-módulos (ou seja, para checkout "tronco"), então pode-se usar seguinte Lua script. Às vezes git submodule update --init --recursive --remote --no-fetch --depth=1 simples comando pode resultar em um erro git irrecuperável. Neste caso, uma necessidade de limpar subdiretório do diretório .git/modules e submodule clone manualmente usando comandos git clone --separate-git-dir. A única complexidade é descobrir o URL , o caminho de diretório .git de submodule e caminho do sub-módulo na árvore superproject.

Observação: o script só é testado contra repositório https://github.com/boostorg/boost.git. Suas peculiaridades: todos os submódulos hospedado no mesmo host e .gitmodules contém apenas relativa 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
Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top