Eu tenho um projeto com um submódulo Git. É de uma URL ssh: // ... e está no commit A. O commit B foi enviado para esse URL, e eu quero que o submódulo recupere o commit e mude para ele.
Agora, meu entendimento é que isso git submodule update
deve ser feito, mas isso não acontece. Não faz nada (sem saída, código de saída com êxito). Aqui está um exemplo:
$ mkdir foo
$ cd foo
$ git init .
Initialized empty Git repository in /.../foo/.git/
$ git submodule add ssh://user@host/git/mod mod
Cloning into mod...
user@host's password: hunter2
remote: Counting objects: 131, done.
remote: Compressing objects: 100% (115/115), done.
remote: Total 131 (delta 54), reused 0 (delta 0)
Receiving objects: 100% (131/131), 16.16 KiB, done.
Resolving deltas: 100% (54/54), done.
$ git commit -m "Hello world."
[master (root-commit) 565b235] Hello world.
2 files changed, 4 insertions(+), 0 deletions(-)
create mode 100644 .gitmodules
create mode 160000 mod
# At this point, ssh://user@host/git/mod changes; submodule needs to change too.
$ git submodule init
Submodule 'mod' (ssh://user@host/git/mod) registered for path 'mod'
$ git submodule update
$ git submodule sync
Synchronizing submodule url for 'mod'
$ git submodule update
$ man git-submodule
$ git submodule update --rebase
$ git submodule update
$ echo $?
0
$ git status
# On branch master
nothing to commit (working directory clean)
$ git submodule update mod
$ ...
Eu também tentei git fetch mod
, que aparece para fazer uma busca (mas não pode, possivelmente, porque não é solicitar uma senha!), Mas git log
e git show
negar a existência de novos commits. Até agora, acabei de rm
usar o módulo e adicioná-lo novamente, mas isso é errado em princípio e tedioso na prática.
git
git-submodules
git-pull
Thanatos
fonte
fonte
--remote
opção, talvez seja útil marcar isso como a resposta aceita e não a abordagem "manual" na resposta de Jason?--remote
é definitivamente uma solução melhor neste momento e, como essa questão foi vinculada a partir de um Github Gist sobre submódulos, acho que seria melhor para os novos leitores ver a nova resposta.hunter2
senha: o)Respostas:
Na
git submodule update
verdade, o comando diz ao Git que você deseja que seus submódulos façam check-out do commit já especificado no índice do superprojeto. Se você deseja atualizar seus submódulos para a confirmação mais recente disponível a partir do controle remoto, será necessário fazer isso diretamente nos submódulos.Então, em resumo:
Ou, se você é uma pessoa ocupada:
fonte
git submodule foreach git pull
git submodule foreach git pull origin master
.git submodule foreach --recursive git pull origin master
.-a
opçãogit commit
"Diga ao comando para preparar automaticamente os arquivos que foram modificados e excluídos, mas os novos arquivos sobre os quais você não contou ao Git não são afetados".O Git 1.8.2 apresenta uma nova opção,,
--remote
que permitirá exatamente esse comportamento. Corridabuscará as alterações mais recentes do upstream em cada submódulo, mesclará e verificará a revisão mais recente do submódulo. Como a documentação coloca:
Isso é equivalente à execução
git pull
em cada submódulo, que geralmente é exatamente o que você deseja.fonte
git pull
em cada submódulo" Para esclarecer, não há diferença (da perspectiva do usuário) entre sua resposta egit submodule foreach git pull
?foreach git pull
apenas fez check-out deles, mas não atualizou o ponteiro do repositório principal para apontar para o commit mais recente do submódulo. Somente com--remote
ele fez apontar para o último commit.No diretório pai do projeto, execute:
Ou se você tiver submódulos recursivos, execute:
Às vezes, isso ainda não funciona, porque, de alguma forma, você tem alterações locais no diretório do submódulo local enquanto o submódulo está sendo atualizado.
Na maioria das vezes, a alteração local pode não ser a que você deseja confirmar. Isso pode ocorrer devido a uma exclusão de arquivo no seu submódulo etc. Se sim, faça uma redefinição no diretório do submódulo local e no diretório pai do projeto, execute novamente:
fonte
Seu projeto principal aponta para um commit específico em que o submódulo deve estar.
git submodule update
tenta verificar a confirmação em cada submódulo que foi inicializado. O submódulo é realmente um repositório independente - apenas criar um novo commit no submódulo e pressionar isso não é suficiente. Você também precisa adicionar explicitamente a nova versão do submódulo no projeto principal.Portanto, no seu caso, você deve encontrar o commit correto no submódulo - vamos assumir que essa é a dica
master
:Agora volte ao projeto principal, prepare o submódulo e confirme:
Agora empurre sua nova versão do projeto principal:
A partir deste momento, se alguém atualizar seu projeto principal,
git submodule update
ele atualizará o submódulo, assumindo que ele foi inicializado.fonte
Parece que dois cenários diferentes estão sendo misturados nesta discussão:
Cenário 1
Usando os ponteiros do meu repositório pai para submódulos, quero verificar o commit em cada submódulo para o qual o repositório pai está apontando, possivelmente depois de primeiro percorrer todos os submódulos e atualizá-los / removê-los do controle remoto.
Isso é, como apontado, feito com
Cenário 2, que eu acho que é o objetivo do OP
Novas coisas aconteceram em um ou mais submódulos, e eu quero 1) extrair essas alterações e 2) atualizar o repositório pai para apontar para o commit HEAD (mais recente) deste / desses submódulos.
Isso seria feito por
Não é muito prático, pois você teria que codificar n caminhos para todos os n submódulos em um script para atualizar os ponteiros de confirmação do repositório pai.
Seria legal ter uma iteração automatizada em cada submódulo, atualizando o ponteiro do repositório pai (usando
git add
) para apontar para a cabeça do submódulo (s).Para isso, criei este pequeno script Bash:
git-update-submodules.sh
Para executá-lo, execute
Elaboração
Primeiro, suponho que o ramo com o nome $ BRANCH (segundo argumento) exista em todos os repositórios. Sinta-se livre para tornar isso ainda mais complexo.
O primeiro par de seções é uma verificação de que os argumentos estão lá. Então eu puxo as coisas mais recentes do repositório pai (eu prefiro usar --ff (avanço rápido) sempre que estou fazendo pulls. Eu me refiz, BTW).
Em seguida, pode ser necessário inicializar algum sub-módulo, se novos submódulos foram adicionados ou ainda não foram inicializados:
Então eu atualizo / puxo todos os submódulos:
Observe algumas coisas: Primeiro, estou encadeando alguns comandos Git usando
&&
- o que significa que o comando anterior deve ser executado sem erros.Após uma possível solicitação bem-sucedida (se novas coisas foram encontradas no controle remoto), faço um esforço para garantir que uma possível confirmação de mesclagem não seja deixada para trás no cliente. Novamente, isso só acontece se uma atração realmente trouxer coisas novas.
Finalmente, a final
|| true
é garantir que o script continue com erros. Para fazer isso funcionar, tudo na iteração deve estar entre aspas duplas e os comandos Git entre parênteses (precedência do operador).A minha parte favorita:
Itere todos os submódulos - com
--quiet
, o que remove a saída 'Entering MODULE_PATH'. Usando'echo $path'
(deve estar entre aspas simples), o caminho para o submódulo é gravado na saída.Essa lista de caminhos relativos ao submódulo é capturada em uma matriz (
$(...)
) - finalmente itere e façagit add $i
para atualizar o repositório pai.Finalmente, uma confirmação com alguma mensagem explicando que o repositório pai foi atualizado. Esse commit será ignorado por padrão, se nada for feito. Empurre isso para a origem e pronto.
Eu tenho um script executando isso em um trabalho de Jenkins que se liga a uma implantação automatizada agendada posteriormente e funciona como um encanto.
Espero que isso ajude alguém.
fonte
pwd
comando imprime o 'caminho absoluto' adequado para cada submódulo presente;--recursive
garante a visita a todos os submódulos, incluindo os submódulos dentro dos submódulos -... que podem estar presentes em um grande projeto. Ambos os métodos causam problemas com diretórios que incluem espaços, por exemplo/c/Users/Ger/Project\ Files/...
, a política é nunca usar espaços em branco em nenhum lugar de nossos projetos.--remote
opção.git submodule update --remote
se comporta aproximadamente da maneira que seu script.The remote branch used defaults to master, but the branch name may be overridden by setting the submodule.<name>.branch option in either .gitmodules or .git/config (with .git/config taking precedence).
não quero editar .gitmodules nem .git / config toda vez que quiser fazer isso em outro ramo que não seja o master. Mas talvez eu tenha perdido alguma coisa? Além disso, o método parece impor mesclagens recursivas (perdendo a possibilidade de avançar rapidamente).Puro e simples, para buscar os submódulos:
E agora continue atualizando-os para a ramificação principal mais recente (por exemplo):
fonte
Observe que, embora a forma moderna de atualização do submódulo seja:
A forma mais antiga era:
Exceto ... essa segunda forma não é realmente "silenciosa".
Veja commit a282f5a (12 Abr 2019) por Nguyễn Thái Ngọc Duy (
pclouds
) .(Incorporado por Junio C Hamano -
gitster
- in commit f1c9f6c , 25 de abr de 2019)E o Git 2.23 (terceiro trimestre de 2019) corrige outro problema: "
git submodule foreach
" não protegeu as opções da linha de comando passadas para o comando para serem executadas em cada submódulo corretamente, quando o "--recursive
opção " estava em uso.Veja commit 30db18b (24 Jun 2019) por Morian Sonnet (
momoson
) .(Incorporado por Junio C Hamano -
gitster
- in commit 968eecb , 09 jul 2019)fonte
Isso puxará todas as confirmações mais recentes.
fonte
No meu caso, eu queria
git
atualizar para o mais recente e, ao mesmo tempo, preencher novamente os arquivos ausentes.O seguinte restaurou os arquivos ausentes (graças aos
--force
quais não parece ter sido mencionado aqui), mas não gerou nenhum novo commit:git submodule update --init --recursive --force
Isso fez:
git submodule update --recursive --remote --merge --force
fonte
@ Jason está correto de uma maneira, mas não totalmente.
O mesmo
git submodule update
ocorre com o checkout, mas é para o commit no índice do repositório que o contém. Ainda não conhece o novo commit upstream. Portanto, vá para o seu submódulo, obtenha a confirmação que você deseja e confirme o estado do submódulo atualizado no repositório principal e faça ogit submodule update
.fonte
git submodule update
, a atualização moverá o submódulo para a confirmação especificada no HEAD atual do superprojeto. (qualquer que seja o commit mais recente no superprojeto que o subprojeto deva estar - esse comportamento, após a explicação na postagem de Jason, me parece lógico) Ele também parece ser buscado, mas apenas no caso em que o subprojeto está no commit incorreto , o que estava aumentando a minha confusão.Aqui está uma linha única impressionante para atualizar tudo para o mais recente no master:
Obrigado a Mark Jaquith
fonte
Se você não conhece a ramificação do host, faça o seguinte:
Ele obterá uma ramificação do repositório principal do Git e, em seguida, para cada submódulo fará um puxão da mesma ramificação.
fonte
Se você deseja fazer o checkout de uma
master
ramificação para cada submódulo - você pode usar o seguinte comando para esse fim:fonte