C'è un modo per fare in modo che git pull aggiorni automaticamente i sottomoduli?


203

C'è un modo per avere automaticamente git submodule update(o preferibilmente git submodule update --initchiamato ogni volta che git pullviene fatto?

Cerchi un'impostazione di configurazione git o un alias git per aiutarti.



1
Perché un alias git è preferibile a un alias shell?
wnoise il

20
gli alias git sono belli perché incapsulano il comando nello spazio dei nomi "git". Puoi anche chiedere perché tutti i comandi git iniziano con "git" invece di avere i loro nomi.
Lily Ballard,

5
Per chiunque lo trovi, le risposte più votate sono attualmente obsolete. La risposta di Kane è precisa: stackoverflow.com/a/49427199/3499424
John Neuhaus

Risposte:


176

A partire da Git 2.14 , puoi usarlo git pull --recurse-submodules(e aliaslo come preferisci).

A partire da Git 2.15 , è possibile impostare submodule.recursesu true per abilitare il comportamento desiderato.

Puoi farlo a livello globale eseguendo:

git config --global submodule.recurse true

3
Confermato con 2.16, l'impostazione su true provocherà git pullanche il recupero di un sottomodulo e l'esecuzione submodule update. Questa deve davvero essere la risposta accettata ora
John Neuhaus,

1
Per impostarlo a livello globale:git config --global submodule.recurse true
wintersolutions,

14
Ero frustrato dai sottomoduli, quindi l'ho fatto. Ora funzionano come mi aspetterei. C'è una ragione per cui non sto pensando che questo non sia il comportamento predefinito?
Ben

9
Dovrebbero abilitare anche quello git clone. E accendilo per impostazione predefinita. Altrimenti, ci sarà sempre un'enorme resistenza all'uso dei sottomoduli, poiché i moduli delle persone non sono sempre sincronizzati :-(
Ciro Santilli 30 冠状 病 六四 事件 法轮功

1
@CiroSantilli新疆改造中心法轮功六四事件Santilli git comandi (come commit, fetch, pull, etc.) sono progettati per essere applicato solo al repository corrente. un sottomodulo è un altro repository e non dovrebbe essere influenzato dai comandi eseguiti nel repository principale per impostazione predefinita. questo è un tipo di decisione progettuale da parte dello sviluppatore git.
anione,

113

git config --global alias.pullall '!git pull && git submodule update --init --recursive'

Se vuoi che gli argomenti vengano passati a git pull, usa invece questo:

git config --global alias.pullall '!f(){ git pull "$@" && git submodule update --init --recursive; }; f'

4
ricordati di usare "git config --global" se vuoi questo alias in tutti i repository git che usi
yoyo

43

A partire da Git 1.7.5 dovrebbe aggiornare automaticamente i sottomoduli di default come si desidera.

[EDIT: per commenti: il nuovo comportamento 1.7.5 è quello di recuperare automaticamente gli ultimi commit per i sottomoduli, ma non di aggiornarli (nel git submodule updatesenso). Quindi le informazioni in questa risposta sono rilevanti come sfondo, ma non sono una risposta completa da sola. Hai ancora bisogno di un alias per estrarre e aggiornare i sottomoduli con un solo comando.]

Il comportamento predefinito, "su richiesta", è di aggiornare i sottomoduli ogni volta che si recupera un commit che aggiorna il commit del sottomodulo e questo commit non si trova già nel clone locale.
Puoi anche averlo aggiornato su ogni recupero o mai (comportamento precedente alla 1.7.5 presumo).
L'opzione di configurazione per modificare questo comportamento è fetch.recurseSubmodules.

Questa opzione può essere impostata su un valore booleano o su on-demand.
Impostandolo su un valore booleano si modifica il comportamento fetche si pullricorre incondizionatamente ai sottomoduli quando impostato su true o per non ricorrere affatto quando impostato su false.

Quando è impostato on-demand(il valore predefinito), fetche pull sarà solo recurse in un modulo popolata quando il suo SuperProject recupera un commit che gli aggiornamenti di riferimento del modulo .

Vedere:

per maggiori informazioni.

git fetch --recurse-submodules[=yes|on-demand|no]

27
Attenzione: come spiegano le risposte di seguito, questo recupera solo automaticamente le modifiche, devi comunque fare un aggiornamento del sottomodulo - quindi la risposta alias è giusta.
Artem,

4
@Artem è corretto. Questa risposta, sebbene utile, non affronta l'intera domanda. Questa impostazione esegue semplicemente a git fetch, non a git submodule update.
Andrew Ferrier,

2
Questa risposta è altamente ingannevole. Anche se usata con git pull, piuttosto che git fetch, questa opzione rende il recupero ricorsivo. Non cambierà affatto quale commit è stato estratto nei sottomoduli. Quindi git submodule updateè ancora necessario, come notato da @Artem.
Mark Amery,

31

Sono sorpreso che nessuno abbia menzionato l'uso di git hook per farlo!

Basta aggiungere i file denominati post-checkoute post-mergenella .git/hooksdirectory dei repository pertinenti e inserire quanto segue in ciascuno di essi:

#!/bin/sh
git submodule update --init --recursive

Dato che hai chiesto specificatamente un alias, supponendo che tu voglia averlo per molti repository, puoi creare un alias che li aggiunge a un repository .git/hooksper te.


2
C'è un modo per rendere questo un ambiente globale? O uno che si ottiene automaticamente quando si controlla il repository?
Raoul Steffen,

3
L'ultima versione di git, 2.9, ha aggiunto un'impostazione denominata core.hooksPathper una directory hooks , vedere i documenti git-configper maggiori dettagli.
taleinat,

1
Per quanto riguarda qualcosa ricevuto automaticamente al momento del check out, ho cercato ma non sono riuscito a trovare nulla del genere. Una fonte ha affermato che questo non è intenzionalmente supportato per problemi di sicurezza, dal momento che potrebbe piuttosto essere facilmente utilizzato per eseguire codice arbitrario su macchine client.
taleinat,

1
Vedo come può essere un problema di sicurezza. Dopotutto, voglio usarlo per eseguire il codice che programma sui computer dei miei colleghi senza doverli istruire.
Raoul Steffen,

1
Questa soluzione è stata il mio primo pensiero, ma poi ho capito che non avrebbe riguardato le persone che usano git pull --rebase:(
Vaz

8

Un alias, come suggerito da Kevin Ballard, è una soluzione perfettamente valida. Solo per lanciare un'altra opzione là fuori, potresti anche usare un gancio post-unione che semplicemente gira git submodule update [--init].


7

È possibile creare un alias per il comando git che gestisce automaticamente l'aggiornamento del sottomodulo. Aggiungi quanto segue al tuo .bashrc

# make git submodules usable
#   This overwrites the 'git' command with modifications where necessary, and
#   calls the original otherwise
git() {
    if [[ $@ == clone* ]]; then
        gitargs=$(echo "$@" | cut -c6-)
        command git clone --recursive $gitargs
    elif [[ $@ == pull* ]]; then
        command git "$@" && git submodule update --init --recursive
    elif [[ $@ == checkout* ]]; then
        command git "$@" && git submodule update --init --recursive
    else
        command git "$@"
    fi
}

1
Invece di un alias per git, puoi aggiungere alias a git tramite il comando alias o creando comandi nel tuo percorso che iniziano con git- (git-bettermodule)
idbrii

7

Come altri hanno già detto, puoi facilmente impostarlo con:

git config --global submodule.recurse true

Tuttavia, se sei come me e hai .gitconfigun'installazione più complessa (il mio ~/.gitconfigfile principale utilizza includeper caricare in altri .gitconfigfile) e non riesci mai a ricordare come convertire tra il gitformato di configurazione della riga di comando e il .gitconfigformato, ecco come aggiungerlo a uno qualsiasi dei tuoi .gitconfigfile:

[submodule]
  recurse = true

0

L'unico modo in cui sono stato in grado di ottenere l'aggiornamento dei sottomoduli e dei sottomoduli nidificati:

git submodule update --remote --merge --recursive; git submodule foreach --recursive "(git add .; git commit -m 'SubmoduleSync'; git push; git pull;);" git add .; git commit -m 'SubmodulesSynced'; git push; git pull;

Avevo difficoltà a creare l'alias tramite terminal a causa delle parentesi, quindi ho dovuto aggiungere manualmente questo a .gitconfig per global:

[alias] supdate = "!git submodule update --remote --merge --recursive; git submodule foreach --recursive '(git add .; git commit -m 'SubmoduleSync'; git push; git pull;);' git add .; git commit -m 'SubmodulesSynced'; git push; git pull;"

Qualche suggerimento su come eseguire automaticamente i comandi o l'alias?

Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.