use - Como posso especificar uma ramificação/tag ao adicionar um submódulo Git?




how to use tag on git (8)

Como o git submodule add -b funciona?

Depois de adicionar um submódulo com uma ramificação específica, um novo repositório clonado (após git submodule update --init ) estará em uma consolidação específica, não na própria ramificação (o git status no submódulo mostra "Not currently on any branch").

Não consigo encontrar nenhuma informação sobre .gitmodules ou .gitmodules .git/config sobre a ramificação do submódulo ou qualquer commit específico, então como o Git descobre isso?

Além disso, é possível especificar uma tag em vez de uma ramificação?

Estou usando a versão 1.6.5.2.


Eu gostaria de acrescentar uma resposta aqui que é apenas um conglomerado de outras respostas, mas acho que pode ser mais completo.

Você sabe que tem um submódulo do Git quando tem essas duas coisas.

  1. Seu .gitmodules tem uma entrada assim:

    [submodule "SubmoduleTestRepo"]
        path = SubmoduleTestRepo
        url = https://github.com/jzaccone/SubmoduleTestRepo.git
    
  2. Você tem um objeto submódulo (chamado SubmoduleTestRepo neste exemplo) em seu repositório Git. GitHub mostra isso como objetos "submódulos". Ou faça git submodule status partir de uma linha de comando. Objetos submódulos Git são tipos especiais de objetos Git, e eles mantêm as informações SHA para um commit específico.

    Sempre que você fizer uma git submodule update , ele preencherá seu submódulo com o conteúdo da confirmação. Ele sabe onde encontrar o commit por causa das informações nos .gitmodules .

    Agora, tudo o que o- -b faz é adicionar uma linha no seu arquivo .gitmodules . Então, seguindo o mesmo exemplo, ficaria assim:

    [submodule "SubmoduleTestRepo"]
        path = SubmoduleTestRepo
        url = https://github.com/jzaccone/SubmoduleTestRepo.git
        branch = master
    

    EDIT: apenas o nome da ramificação é suportado acima, não SHA ou TAG.

    O objeto de submódulo ainda está apontando para uma confirmação específica. A única coisa que a opção -b compra é a capacidade de adicionar um sinalizador --remote à sua atualização, de acordo com a resposta da Vogella:

    git submodule update --remote
    

    Em vez de preencher o conteúdo do submódulo para o commit apontado pelo submódulo, ele substitui o commit pelo commit mais recente no branch master, ENTÃO ele preenche o submódulo com o commit. Isso pode ser feito em duas etapas pela resposta djacobs7. Como você já atualizou a confirmação para a qual o objeto de submódulo está apontando, você deve submeter o objeto de submódulo alterado ao seu repositório Git.

    git submodule add -b não é uma maneira mágica de manter tudo atualizado com um branch. Ele simplesmente adiciona informações sobre uma ramificação no arquivo .gitmodules e oferece a opção de atualizar o objeto de submódulo para a confirmação mais recente de uma ramificação especificada antes de preenchê-lo.


Eu tenho isso no meu arquivo .gitconfig. Ainda é um rascunho, mas provou ser útil a partir de agora. Isso me ajuda a sempre recolocar os submódulos em seu ramo.

[alias]

######################
#
#Submodules aliases
#
######################


#git sm-trackbranch : places all submodules on their respective branch specified in .gitmodules
#This works if submodules are configured to track a branch, i.e if .gitmodules looks like :
#[submodule "my-submodule"]
#   path = my-submodule
#   url = [email protected]/my-submodule.git
#   branch = my-branch
sm-trackbranch = "! git submodule foreach -q --recursive 'branch=\"$(git config -f $toplevel/.gitmodules submodule.$name.branch)\"; git checkout $branch'"

#sm-pullrebase :
# - pull --rebase on the master repo
# - sm-trackbranch on every submodule
# - pull --rebase on each submodule
#
# Important note :
#- have a clean master repo and subrepos before doing this !
#- this is *not* equivalent to getting the last committed 
#  master repo + its submodules: if some submodules are tracking branches 
#  that have evolved since the last commit in the master repo,
#  they will be using those more recent commits !
#
#  (Note : On the contrary, git submodule update will stick 
#to the last committed SHA1 in the master repo)
#
sm-pullrebase = "! git pull --rebase; git submodule update; git sm-trackbranch ; git submodule foreach 'git pull --rebase' "

# git sm-diff will diff the master repo *and* its submodules
sm-diff = "! git diff && git submodule foreach 'git diff' "

#git sm-push will ask to push also submodules
sm-push = push --recurse-submodules=on-demand

#git alias : list all aliases
#useful in order to learn git syntax
alias = "!git config -l | grep alias | cut -c 7-"

Nota: O Git 1.8.2 adicionou a possibilidade de rastrear ramificações. Veja algumas das respostas abaixo.

É um pouco confuso para se acostumar com isso, mas os submódulos não estão em um ramo. Eles são, como você diz, apenas um ponteiro para um commit particular do repositório do submódulo.

Isso significa que, quando alguém faz check-out do seu repositório, ou puxa seu código, e faz o git submódulo update, o submódulo é retirado desse commit específico.

Isso é ótimo para um submódulo que não muda com frequência, porque então todos no projeto podem ter o submódulo no mesmo commit.

Se você quiser mover o submódulo para uma tag específica:

cd submodule_directory
git checkout v1.0
cd ..
git add submodule_directory
git commit -m "moved submodule to v1.0"
git push

Então, outro desenvolvedor que deseja ter o submodule_directory alterado para essa tag, isso

git pull
git submodule update

git pull alterações para as quais o commit do seu submódulo aponta. git submodule update realmente se funde no novo código.


O único efeito de escolher uma ramificação para um submódulo é que, sempre que você passar a opção --remote na linha de comando git submodule update , o Git fará o check out no modo HEAD separado (se o comportamento padrão --checkout for selecionado) o mais recente commit daquela ramificação remota selecionada.

Você deve ser particularmente cuidadoso ao usar este recurso de rastreamento de ramificação remota para submódulos Git se você trabalhar com clones superficiais de submódulos. A ramificação que você escolher para essa finalidade nas configurações do submódulo NÃO é aquela que será clonada durante a git submodule update --remote . Se você passar também o parâmetro --depth e não instruir o Git sobre qual ramificação você deseja clonar - e na verdade você não pode na linha de comando git submodule update !! -, implicitamente se comportará como explicado na documentação do git-clone(1) para git clone --single-branch quando o parâmetro explícito --branch estiver faltando e, portanto, ele irá clonar apenas o branch primário .

Sem surpresa, após o estágio clone realizado pelo comando git submodule update , ele finalmente tentará verificar a confirmação mais recente da ramificação remota que você configurou anteriormente para o submódulo e, se essa não for a primária, é não faz parte do seu clone superficial local e, portanto, falhará com

fatal: precisava de uma única revisão

Não é possível encontrar a origem atual / revisão NotThePrimaryBranch no caminho do submódulo 'mySubmodule'


Observe que, se você tiver um submódulo existente que ainda não esteja rastreando uma ramificação , ( se você tiver o git 1.8.2+ ):

  • Certifique-se de que o repo pai saiba que seu submódulo agora rastreia uma ramificação:

    cd /path/to/your/parent/repo
    git config -f .gitmodules submodule.<path>.branch <branch>
    
  • Certifique-se de que seu submódulo seja realmente o mais recente desse ramo:

    cd path/to/your/submodule
    git checkout -b branch --track origin/branch
      # if the master branch already exist:
      git branch -u origin/master master
    

(com 'origem' sendo o nome do repo remoto a montante, o submódulo foi clonado a partir de.
Um git remote -v dentro desse submódulo irá exibi-lo. Geralmente, é "origem")

  • Não se esqueça de gravar o novo estado do seu submódulo no repositório pai:

    cd /path/to/your/parent/repo
    git add path/to/your/submodule
    git commit -m "Make submodule tracking a branch"
    
  • A atualização subsequente para esse submódulo terá que usar a opção --remote :

    # update your submodule
    # --remote will also fetch and ensure that
    # the latest commit from the branch is used
    git submodule update --remote
    
    # to avoid fetching use
    git submodule update --remote --no-fetch 
    

Note que com o Git 2.10+ (T3 2016), você pode usar ' . 'como um nome de ramificação:

O nome da ramificação é registrado como submodule.<name>.branch in .gitmodules for update --remote .
Um valor especial de . é usado para indicar que o nome da ramificação no submódulo deve ser o mesmo nome da ramificação atual no repositório atual .

Se você quiser atualizar todos os seus submódulos seguindo uma ramificação:

    git submodule update --recursive --remote

Note que o resultado, para cada submódulo atualizado, será quase sempre um HEAD separado , como nota Dan Cameron em sua resposta .

( Clintm observa nos comentários que, se você executar git submodule update --remote e o resultado sha1 for o mesmo que o submódulo no qual o submódulo está atualmente, ele não fará nada e deixará o submódulo ainda "nessa ramificação" e não em estado de cabeça destacada.)

Para garantir que a ramificação esteja realmente com check-out (e que não modifique o SHA1 da entrada especial que representa o submódulo para o repositório pai), ele sugere:

git submodule foreach -q --recursive 'branch="$(git config -f $toplevel/.gitmodules submodule.$name.branch)"; git checkout $branch'

Cada submódulo ainda referenciará o mesmo SHA1, mas se você fizer novos commits, você poderá empurrá-los porque eles serão referenciados pelo branch que você deseja que o submódulo monitore.
Após esse push dentro de um submódulo, não se esqueça de voltar ao repositório pai, adicionar, confirmar e enviar o novo SHA1 para esses submódulos modificados.

Observe o uso de $toplevel , recomendado nos comentários de Alexander Pogrebnyak .
$toplevel foi introduzido no git1.7.2 em maio de 2010: commit f030c96 .

contém o caminho absoluto do diretório de nível superior (onde .gitmodules é).

dtmland acrescenta nos comentários :

O script foreach falhará ao finalizar os submódulos que não estão seguindo uma ramificação.
No entanto, este comando fornece os dois:

 git submodule foreach -q --recursive 'branch="$(git config -f $toplevel/.gitmodules submodule.$name.branch)"; [ "$branch" = "" ] && git checkout master || git checkout $branch' –

O mesmo comando, mas mais fácil de ler:

git submodule foreach -q --recursive \
    'branch="$(git config -f $toplevel/.gitmodules submodule.$name.branch)"; \
     [ "$branch" = "" ] && \
     git checkout master || git checkout $branch' –

umläute refina o comando do dtmland com uma versão simplificada nos comentários :

git submodule foreach -q --recursive 'git checkout $(git config -f $toplevel/.gitmodules submodule.$name.branch || echo master)'

várias linhas:

git submodule foreach -q --recursive \
  'git checkout \
  $(git config -f $toplevel/.gitmodules submodule.$name.branch || echo master)'

Os submodules do Git são um pouco estranhos - eles estão sempre no modo "head desanexado" - eles não atualizam para o commit mais recente em um branch como você poderia esperar.

Isso faz algum sentido quando você pensa sobre isso, no entanto. Digamos que eu crie repositório foo com barra de submódulos. Eu empurro minhas mudanças e digo para você verificar o commit a7402be do repositório foo .

Então imagine que alguém comete uma alteração na barra de repositório antes de poder fazer o seu clone.

Quando você checa commit a7402be do repositório foo , espera obter o mesmo código que eu enviei. É por isso que os submódulos não são atualizados até que você os informe explicitamente e faça um novo commit.

Pessoalmente, acho que os submódulos são a parte mais confusa do Git. Há muitos lugares que podem explicar submódulos melhor do que eu. Eu recomendo Pro Git por Scott Chacon.


Um exemplo de como eu uso submodules Git.

  1. Crie um novo repositório
  2. Em seguida, clone outro repositório como um submódulo
  3. Então nós temos esse submódulo usando uma tag chamada V3.1.2
  4. E então nos comprometemos.

E isso parece um pouco assim:

git init 
vi README
git add README
git commit 
git submodule add git://github.com/XXXXX/xxx.yyyy.git stm32_std_lib
git status

git submodule init
git submodule update

cd stm32_std_lib/
git reset --hard V3.1.2 
cd ..
git commit -a

git submodule status 

Talvez isso ajude (mesmo que eu use uma tag e não uma ramificação)?


Usamos Quack para puxar um módulo específico de outro repositório Git. Precisamos extrair código sem toda a base de código do repositório fornecido - precisamos de um módulo / arquivo muito específico daquele enorme repositório e devemos ser atualizados toda vez que rodarmos o update.

Então, conseguimos isso da seguinte maneira:

Criar configuração

name: Project Name

modules:
  local/path:
    repository: https://github.com/<username>/<repo>.git
    path: repo/path
    branch: dev
  other/local/path/filename.txt:
    repository: https://github.com/<username>/<repo>.git
    hexsha: 9e3e9642cfea36f4ae216d27df100134920143b9
    path: repo/path/filename.txt

profiles:
  init:
    tasks: ['modules']

Com a configuração acima, ele cria um diretório a partir do repositório GitHub fornecido, conforme especificado na configuração do primeiro módulo, e o outro é extrair e criar um arquivo do repositório fornecido.

Outros desenvolvedores só precisam executar

$ quack

E puxa o código das configurações acima.





git-submodules