Submodule Git em nu remoto

Eu configurei meu ambiente para poder enviar para um repository remoto, usei estes comandos para configurar o repository remoto:

$ mkdir ~/website.git && cd ~/website.git $ git init --bare 

E

 $ cat > hooks/post-receive #!/bin/sh GIT_WORK_TREE=/var/www/website git checkout -f $ chmod +x hooks/post-receive 

E no meu ambiente local:

 $ git remote add web ssh://website.com/home/website.git $ git push web +master:refs/heads/master 

Agora eu posso implantar para este remoto usando o git push web e tudo funciona muito bem ..

O problema: submódulos

Eu tenho alguns submodules no meu projeto que não estão sendo inicializados / atualizados no repository remoto … Eu não posso executar o git submodule update no bare porque ele é nu, e eu não posso executá-lo no /var/www/website folder porque é apenas uma cópia dos arquivos e não um git repo.

Um caminho possível pode ser:

  • para configurar /var/www/website como um repo (não nua)
  • tenha o seu gancho post-receive do seu repository nu:
    • defina GIT_DIR e GIT_WORK_TREE para o GIT_WORK_TREE não nu em /var/www/website
    • cd /var/ww/website
    • git pull ~/website
    • git submodule update (um pouco como em ” Como faço para iniciar / atualizar um sub-módulo git em uma tree de trabalho depois de empurrar para um diretório de trabalho vazio? “)

Em outras palavras:
Puxar do repo nu em vez de tentar sair de um repository nu: um repository não-nu deve ser capaz de acomodar a etapa de git submodule update .

Um exemplo de script pode parecer

 #!/bin/sh # Get the latest code cd /path/to/bare/repo # Set git variables GIT_WORK_TREE=/var/www/website GIT_DIR=/var/www/website/.git # Go to website and pull cd /var/www/website git pull /path/to/bare/repo git submodule update --init --recursive # Run additional build stuff here 

Eu descobri outra solução que parece bastante limpa para mim. Apenas dê git todas as informações necessárias para executar o material do submódulo:

 $ cd /path/to/your/git_work_tree $ git --git-dir=/path/to/your/bare_repo.git --work-tree=. submodule init $ git --git-dir=/path/to/your/bare_repo.git --work-tree=. submodule update 

Eu tropecei nesse tópico dois dias atrás enquanto eu lutava com o mesmo problema. Depois de finalmente chegar a uma solução legal e arrumada, escrevi um artigo sobre isso aqui:

Git push com submódulos: um guia prático

Eu percebi que, se eu for push para um repo nu, apenas para usar post-receive para pull para um repository não-nu, eu poderia muito bem manter isso simples e push diretamente para o repository não-nu. Este é um caso claro em que a “melhor prática” de apenas empurrar para um repository nu está apenas adicionando complexidade.

Em caso de apodrecimento do link, colarei minha solução aqui, ignorando os bits em que me deparo com os mesmos problemas que tenho certeza que você fez.


Primeiro, vamos criar um gancho universal de post-receive , que não precisarei alterar por repository:

 [aaron@aaronadams]$ cat > /usr/local/share/git-core/templates/hooks/post-receive.sample #!/bin/sh # # An example hook script to update the working tree, including its # submodules, after receiving a push. # # This hook requires core.worktree to be explicitly set, and # receive.denyCurrentBranch to be set to false. # # To enable this hook, rename this file to "post-receive". # Read standard input or hook will fail while read oldrev newrev refname do : done # Unset GIT_DIR or the universe will implode unset GIT_DIR # Change directory to the working tree; exit on failure cd `git config --get core.worktree` || exit # Force checkout git checkout --force # Force update submodules git submodule update --init --recursive --force [aaron@aaronadams]$ chmod +x /usr/local/share/git-core/templates/hooks/post-receive.sample 

Agora vamos em frente e quebrar todas as regras.

Vamos inicializar um repository Git não-nu , diretamente em nosso diretório de sites; verifique se ele pode receber do git push ; defina explicitamente sua tree de trabalho para seu diretório pai; e habilitar nosso gancho que acabamos de criar.

 [aaron@aaronadams]$ cd /var/www/vhosts/aaronadams.ca/sites/staging.aaronadams.ca [aaron@aaronadams]$ git init && git config --bool receive.denyCurrentBranch false && git config --path core.worktree ../ && mv .git/hooks/post-receive.sample .git/hooks/post-receive Initialized empty Git repository in /var/www/vhosts/aaronadams.ca/sites/staging.aaronadams.ca/.git/ 

Finalmente, na nossa máquina local, vamos mudar o nosso controle remoto para refletir a localização do nosso novo repository, e empurrar.

 [aaron@aaronadams]$ git remote set-url staging aaron@aaronadams.ca:sites/staging.aaronadams.ca [aaron@aaronadams]$ git push staging master remote: Submodule 'codeigniter' (git://github.com/EllisLab/CodeIgniter.git) registered for path 'codeigniter' remote: Cloning into 'codeigniter'... remote: Submodule path 'codeigniter': checked out 'fd24adf31255822d6aa9a5d2dce9010ad2ee4cf0' To aaron@aaronadams.ca:sites/staging.aaronadams.ca * [new branch] master -> master 

Caramba, funcionou!

Este método não apenas é compatível com submódulos, mas também requer apenas um comando para configurar um novo repository remoto (o que, bem, consiste em quatro comandos). Também mantém o repository e a tree de trabalho no mesmo local; e sem caminhos absolutos necessários em nossa configuração ou arquivos de gancho, agora é completamente portátil também.


Espero que esta resposta ajude alguém tanto quanto os posts do Stack Exchange de todos os outros me ajudaram nos últimos dois dias!