Existe uma maneira de fazer o git pull atualizar automaticamente os submódulos?

203

Existe uma maneira de ter automaticamente git submodule update(ou de preferência git submodule update --initchamado sempre que git pullfor feito?

Procurando uma configuração de configuração do git ou um alias do git para ajudar com isso.

philfreo
fonte
4
Relacionados: stackoverflow.com/questions/1899792/...
philfreo
1
Por que um alias do git é preferível a um alias do shell?
Wnoise
20
Os aliases do git são bons porque encapsula o comando no espaço de nomes "git". Você também pode perguntar por que todos os comandos git começam com "git" em vez de ter seus próprios nomes.
Lily Ballard
5
Para quem encontrar isso, as respostas mais votadas estão desatualizadas. A resposta de Kane é preciso: stackoverflow.com/a/49427199/3499424
John Neuhaus

Respostas:

176

No Git 2.14 , você pode usar git pull --recurse-submodules(e aliasar para o que quiser).

No Git 2.15 , você pode definir submodule.recursecomo true para ativar o comportamento desejado.

Você pode fazer isso globalmente executando:

git config --global submodule.recurse true
Kane
fonte
3
Confirmado com 2.16, definir como true fará com git pullque também busque um submódulo e execute submodule update. Este realmente precisa ser a resposta aceita agora
John Neuhaus
1
Para definir isso globalmente:git config --global submodule.recurse true
wintersolutions
14
Fiquei frustrado com os submódulos, então fiz isso. Agora eles funcionam como eu esperaria. Existe uma razão pela qual não estou pensando que esse não é o comportamento padrão?
Ben
9
Eles devem permitir isso git clonetambém. E ativá-lo por padrão. Caso contrário, sempre haverá uma enorme resistência ao uso de submódulos, pois os módulos das pessoas sempre ficam fora de sincronia :-(
Ciro Santilli 30郝海东
1
@CiroSantilli新疆改造中心法轮功六四事件Santilli git comandos (como commit, fetch, pull, etc.) são concebidos para ser aplicado apenas para o repositório corrente. um submódulo é outro repositório e não deve ser afetado por comandos executados no repositório pai por padrão. esse é um tipo de decisão de design do desenvolvedor do git.
anion
113

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

Se você deseja que os argumentos sejam passados ​​para o git pull, use-o:

git config --global alias.pullall '!f(){ git pull "$@" && git submodule update --init --recursive; }; f'
Lily Ballard
fonte
4
lembre-se de usar "git configuração --global" se você quiser este alias em todos os repos git que você usa
yoyo
43

A partir do Git 1.7.5, ele deve atualizar os submódulos automaticamente por padrão, como você deseja.

[EDIT: por comentários: o novo 1.7.5 comportamento é automaticamente buscar as últimas commits para submódulos, mas não para atualizar -los (no git submodule updatesentido). Portanto, as informações nesta resposta são relevantes como pano de fundo, mas não são uma resposta completa por si só. Você ainda precisa de um alias para extrair e atualizar submódulos em um comando.]

O comportamento padrão, "sob demanda", é atualizar submódulos sempre que você buscar uma confirmação que atualize a submissão do submódulo, e essa confirmação ainda não está localizada no seu clone local.
Você também pode atualizá-lo a cada busca ou nunca (comportamento anterior à 1.7.5, presumo).
A opção de configuração para alterar esse comportamento é fetch.recurseSubmodules.

Esta opção pode ser definida como um valor booleano ou como on-demand.
Configurá-lo como booleano altera o comportamento de fetche pullrecursivamente incondicionalmente em submódulos quando definido como true ou de não recursar quando definido como false.

Quando definido como on-demand(o valor padrão), fetche pull retornará apenas para um sub-módulo preenchido quando seu superprojeto recuperar uma confirmação que atualiza a referência do sub-módulo .

Vejo:

Para maiores informações.

git fetch --recurse-submodules[=yes|on-demand|no]
Christopher Rogers
fonte
27
Cuidado: como as respostas abaixo explicam, isso apenas busca as alterações automaticamente, você ainda precisa fazer uma atualização no submódulo - para que a resposta do alias esteja correta.
Artem
4
@Artem está correto. Essa resposta, embora útil, não aborda a questão inteira. Essa configuração simplesmente executa a git fetch, não a git submodule update.
precisa
2
Essa resposta é altamente enganosa. Mesmo quando usada com git pull, em vez de git fetch, esta opção apenas torna a busca recursiva. Ele não mudará qual commit é verificado nos submódulos. Portanto, git submodule updateainda é necessário, conforme observado pelo @Artem.
Mark Amery
31

Estou surpreso que ninguém tenha mencionado o uso de ganchos git para fazer isso!

Basta adicionar arquivos nomeados post-checkoute post-mergeao seu .git/hooksdiretório de repositórios relevantes e colocar o seguinte em cada um deles:

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

Como você solicitou um alias especificamente, assumindo que deseja ter isso para muitos repositórios, é possível criar um alias que os adicione aos repositórios .git/hookspara você.

taleinat
fonte
2
Existe uma maneira de tornar isso um cenário global? Ou um que você recebe automaticamente ao fazer o check-out do repositório?
Raoul Steffen
3
A versão mais recente do git, 2.9, adicionou uma configuração nomeada core.hooksPathpara um diretório hooks , consulte a documentação para git-configobter mais detalhes.
21416 Taleinat
1
Quanto a algo recebido automaticamente no check-out, procurei, mas não consegui encontrar nada do tipo. Uma fonte mencionou que, de propósito, isso não é suportado por questões de segurança, pois poderia ser usado com facilidade para executar código arbitrário nas máquinas clientes.
taleinat
1
Vejo como isso pode ser um problema de segurança. Afinal, eu quero usá-lo para executar o código que eu programo nos computadores dos meus colegas de trabalho sem precisar instruí-los.
Raoul Steffen
1
Esta solução foi o meu primeiro pensamento, mas depois percebi que não cobriria as pessoas que usam git pull --rebase:(
Vaz
8

Um alias, como sugerido por Kevin Ballard, é uma solução perfeitamente boa. Apenas para lançar outra opção, você também pode usar um gancho de pós-mesclagem que simplesmente roda git submodule update [--init].

Cascabel
fonte
7

Você pode criar um alias para o comando git que lida automaticamente com a atualização do sub-módulo. Adicione o seguinte ao seu .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
}
Branden Ghena
fonte
1
Em vez de um alias para git, você pode adicionar aliases para git através do comando alias ou através da criação de comandos em seu caminho que começam com git- (git-bettermodule)
idbrii
7

Como outros já mencionaram, você pode facilmente definir isso com:

git config --global submodule.recurse true

No entanto, se você gosta de mim e tem uma .gitconfigconfiguração mais complexa (meu ~/.gitconfigarquivo principal usa includepara carregar em outros .gitconfigarquivos), e você nunca se lembra de como converter entre o gitformato de configuração da linha de comando e o .gitconfigformato, veja como adicioná-lo para qualquer um dos seus .gitconfigarquivos:

[submodule]
  recurse = true
JacobEvelyn
fonte
0

A única maneira de conseguir atualizar os submódulos e submódulos aninhados:

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;

Eu estava lutando para criar o alias através do terminal devido aos colchetes, então tive que adicioná-lo manualmente ao .gitconfig para 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;"

Alguma sugestão de como executar os comandos ou o alias automaticamente?

Sauli Kiviranta
fonte