Domanda

Stiamo usando i sottomoduli git per gestire un paio di grandi progetti che hanno dipendenze da molte altre librerie che abbiamo sviluppato. Ogni libreria è un repository separato portato nel progetto dipendente come sottomodulo. Durante lo sviluppo, spesso vogliamo semplicemente prendere l'ultima versione di ogni sottomodulo dipendente.

Git ha un comando integrato per farlo? In caso contrario, che ne dici di un file batch di Windows o simile che può farlo?

È stato utile?

Soluzione

Se è la prima volta fai il checkout di un repository, devi prima usare --init :

git submodule update --init --recursive

Per git 1.8.2 o superiore è stata aggiunta l'opzione --remote per supportare l'aggiornamento agli ultimi suggerimenti delle filiali remote:

git submodule update --recursive --remote

Questo ha l'ulteriore vantaggio di rispettare qualsiasi " non default " i rami specificati nei file .gitmodules o .git / config (se ne hai uno, il default è origin / master, nel qual caso alcune delle altre risposte qui sarebbero funziona anche).

Per git 1.7.3 o versioni successive puoi usare (ma i trucchi qui sotto su quale aggiornamento si applica ancora):

git submodule update --recursive

o

git pull --recurse-submodules

se si desidera eseguire il pull dei sottomoduli agli ultimi commit, al di là di ciò a cui punta il repository.

Vedi git-submodule (1) per dettagli

Altri suggerimenti

Se è necessario inserire elementi per i sottomoduli nei repository dei sottomoduli, utilizzare

git pull --recurse-submodules
  

una funzionalità git appresa per la prima volta in 1.7.3.

Ma questo non verificherà i commit (quelli indicati dal repository principale) nei sottomoduli

Per verificare gli commit corretti nei sottomoduli, è necessario aggiornarli dopo averlo tirato usando

git submodule update --recursive --remote

Su init esegue il seguente comando:

git submodule update --init --recursive

dall'interno della directory git repo, funziona meglio per me.

Verranno estratti tutti gli ultimi inclusi i sottomoduli.

Explained

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.

Dopodiché puoi semplicemente eseguire:

git submodule update --recursive

dall'interno della directory git repo, funziona meglio per me.

Verranno estratti tutti gli ultimi inclusi i sottomoduli.

Nota: è del 2009 e potrebbe essere stato buono allora, ma ora ci sono opzioni migliori.

Lo usiamo. Si chiama 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 inserirlo in una directory bin adatta (/ usr / local / bin). Se su Windows, potrebbe essere necessario modificare la sintassi per farlo funzionare :)

Aggiornamento:

In risposta al commento dell'autore originale su come inserire tutti i HEAD di tutti i sottomoduli - questa è una buona domanda.

Sono abbastanza sicuro che git non abbia un comando per questo internamente. Per fare ciò, dovresti identificare cosa è realmente HEAD per un sottomodulo. Potrebbe essere semplice come dire master è il ramo più aggiornato, ecc ...

In seguito, crea un semplice script che procede come segue:

  1. controlla git submodule status per " modificato " repository. Il primo carattere delle righe di output indica questo. Se un sub-repo viene modificato, potresti NON voler procedere.
  2. per ogni repo elencato, cd nella sua directory ed esegui git checkout master & amp; & amp; git pull . Controlla errori.
  3. Alla fine, ti suggerisco di stampare un display all'utente per indicare lo stato corrente dei sottomoduli - forse spingerli ad aggiungere tutto e impegnarsi?

Vorrei menzionare che questo stile non è proprio quello per cui sono stati progettati i sottomoduli git. In genere, vuoi dire " LibraryX " è nella versione "2,32"; e rimarrà tale fino a quando non lo dirò a " upgrade " ;.

Questo è, in un certo senso, quello che stai facendo con lo script descritto, ma solo più automaticamente. È necessaria la cura!

Aggiornamento 2:

Se sei su una piattaforma Windows, potresti voler usare Python per implementare lo script in quanto è molto capace in queste aree. Se sei su unix / linux, allora suggerisco solo uno script bash.

Hai bisogno di chiarimenti? Pubblica un commento.

Henrik è sulla buona strada. Il comando 'foreach' può eseguire qualsiasi script shell arbitrario. Due opzioni per estrarre l'ultima potrebbe essere,

git submodule foreach git pull origin master

e

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

Questo eseguirà l'iterazione attraverso tutti i sottomoduli inizializzati ed eseguirà i comandi dati.

Quanto segue ha funzionato per me su Windows.

git submodule init
git submodule update

Modifica :

Nei commenti è stato sottolineato (da philfreo ) che è richiesta l'ultima versione. Se sono presenti sottomoduli nidificati che devono trovarsi nella loro ultima versione:

git submodule foreach --recursive git pull

----- Commento obsoleto di seguito -----

Non è questo il modo ufficiale per farlo?

git submodule update --init

Lo uso ogni volta. Nessun problema finora.

Modifica

Ho appena scoperto che puoi usare:

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

Che tirerà anche in modo ricorsivo tutti i sottomoduli, cioè le dipendenze.

Come può succedere che il ramo predefinito dei tuoi sottomoduli sia non master , è così che automatizzo gli aggiornamenti completi dei sottomoduli 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'

Prima volta

Clone and Init Submodule

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

Resto

Durante lo sviluppo basta estrarre e aggiornare il sottomodulo

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

Aggiorna il sottomodulo Git all'ultimo commit sull'origine

git submodule foreach git pull origin master

Il modo preferito dovrebbe essere inferiore

git submodule update --remote --merge

nota: gli ultimi due comandi hanno lo stesso comportamento

Non so da quale versione di git funzioni, ma è quello che stai cercando:

git submodule update --recursive

Lo uso con git pull anche per aggiornare il repository root:

git pull && git submodule update --recursive

Guarda http://lists.zerezo.com/git/msg674976.html che introduce un parametro --track

Le risposte di cui sopra sono buone, tuttavia abbiamo usato git-hook per renderlo più semplice, ma risulta che in git 2.14 , puoi impostare git config submodule.recurse su true per abilitare l'aggiornamento dei sottomoduli quando si tira nel tuo repository git.

Ciò avrà l'effetto collaterale di spingere tutti i cambiamenti dei sottomoduli che hai se sono comunque sui rami, ma se hai già bisogno di quel comportamento già questo potrebbe fare il lavoro.

Può essere fatto usando:

git config submodule.recurse true

Git per Windows 2.6.3 :

git submodule update --rebase --remote

L'ho fatto adattando gahooa 's risposta sopra :

Integralo con un git [alias] ...

Se il tuo progetto genitore ha qualcosa del genere in .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

Aggiungi qualcosa di simile all'interno del tuo .gitconfig

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

Quindi, per aggiornare i sottomoduli, eseguire:

git updatesubs

Ne ho un di esempio in il mio repo setup ambiente .

Ecco la riga di comando per estrarre da tutti i tuoi repository git che siano o meno sottomoduli:

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

Se lo esegui nel tuo repository git principale, puoi sostituire " $ ROOT " in . .

Tutto quello che devi fare ora è un semplice git checkout

Assicurati solo di abilitarlo tramite questa configurazione globale: git config --global submodule.recurse true

Dal livello superiore nel repository:

git submodule foreach git checkout develop
git submodule foreach git pull

Questo cambierà tutti i rami per sviluppare e tirare gli ultimi

Penso che dovrai fare uno script per farlo. Ad essere sincero, potrei installare Python per farlo in modo da poter usare os.walk per cd in ogni directory ed emettere i comandi appropriati. L'uso di Python o di un altro linguaggio di scripting, diverso dal batch, ti consentirebbe di aggiungere / rimuovere facilmente sottoprogetti senza dover modificare lo script.

Nota: non troppo semplice, ma fattibile e ha i suoi vantaggi unici.

Se si desidera clonare solo la revisione HEAD di un repository e solo HEAD di tutti i suoi sottomoduli (cioè per effettuare il checkout " trunk "), si può usa il seguente script Lua . A volte il semplice comando git submodule update --init --recursive --remote --no-fetch --depth = 1 può causare un errore git irrecuperabile. In questo caso è necessario ripulire la sottodirectory della directory .git / modules e clonare il sottomodulo manualmente usando il comando git clone --separate-git-dir . L'unica complessità è scoprire URL , il percorso della directory .git del sottomodulo e il percorso del sottomodulo nell'albero del superprogetto.

Nota: lo script viene testato solo sul repository https://github.com/boostorg/boost.git . Le sue peculiarità: tutti i sottomoduli ospitati sullo stesso host e .gitmodules contengono solo URL s relativi

-- 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
Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top