Como adiciono um submódulo a um subdiretório?

310

Eu tenho um repositório Git ~/.janus/com um monte de submódulos nele. Quero adicionar um submódulo ~/.janus/snipmate-snippets/snippets/, mas quando executo git submodule add <[email protected]:...>o snipmate-snippetsdiretório, recebo a seguinte mensagem de erro:

You need to run this command from the toplevel of the working tree.

Portanto, a pergunta é: como adiciono um submódulo ao snipmate-snippetsdiretório?

Robert Audi
fonte
Ir para o diretório raiz de um repositório git para comandos do submódulo não será mais um requisito (em breve). Veja minha resposta abaixo
VonC
3
git submodule add -b <branch> <url> <relative_path_4m_root>
27518 parasrish

Respostas:

439

Você entra ~/.januse corre:

git submodule add <git@github ...> snipmate-snippets/snippets/

Se você precisar de mais informações sobre submódulos (ou git em geral), o ProGit é bastante útil.

BergmannF
fonte
parece uma boa idéia para adicionar ramo quando acrescentando outra forma cabeça fica facilmente destacado: git -b submodule add <ramo> <repositório> [<submodule-path>]
deann
1
Para mim, isso estava causando 'subprojects' already exists in the index (eu estava usando subprojetos como o nome do diretório) . Em vez disso, o que ajudou foi a resposta do VonC abaixo, isto é cd subprojects, fazer e depois git submodule add <get@github …>sem o caminho.
Hi-Angel
83

Observe que, iniciando o git1.8.4 (julho de 2013), você não precisaria mais voltar ao diretório raiz.

 cd ~/.janus/snipmate-snippets
 git submodule add <git@github ...> snippets

( Bouke Versteegh comenta que você não precisa usar /., como em snippets/.: snippetsé suficiente)

Consulte commit 091a6eb0feed820a43663ca63dc2bc0bb247bbae :

submódulo: elimine o requisito de nível superior

Use a nova rev-parse --prefixopção para processar todos os caminhos fornecidos ao comando submodule, eliminando o requisito de que seja executado no nível superior do repositório.

Como a interpretação de um URL relativo ao submódulo depende se " remote.origin.url" está configurada ou não , bloqueie explicitamente URLs relativos em " git submodule add" quando não estiver no nível superior da árvore de trabalho.

Assinado por: John Keeping

Depende da confirmação 12b9d32790b40bf3ea49134095619700191abf1f

Isso faz com que ' git rev-parse' se comporte como se tivesse sido chamado a partir do subdiretório especificado de um repositório, com a diferença de que todos os caminhos de arquivos impressos sejam prefixados com o caminho completo da parte superior da árvore de trabalho .

Isso é útil para scripts de shell nos quais podemos querer cdchegar ao topo da árvore de trabalho, mas precisamos lidar com os caminhos relativos fornecidos pelo usuário na linha de comando.

VonC
fonte
Muito obrigado! Percebi que a trilha /.não é necessária, o git criará os trechos de diretório sem ela.
Bouke Versteegh
@BoukeVersteegh Interesting. Incluímos seu comentário na resposta para obter mais visibilidade.
VonC
Estou na versão 2.7.4 do git, mas ainda estou recebendo esta mensagem de erro Relative path can only be used from the toplevel of the working tree. Estou fazendo #git submodule add ../../../functest
FlyingAura
@ user3426358 sim, isso é esperado: a resposta acima é sobre a capacidade de fazer um submodelo git adicionado a partir de qualquer subpasta do repositório principal, não apenas da pasta raiz. É não sobre como fazer referência o repo remoto submodule com um caminho relativo. Se você o fizer, receberá a mensagem de erro exibida.
VonC
@ user3426358 E, a propósito, essa mensagem de erro (que você vê: " Relative path can only be used from the toplevel of the working tree") não é a da pergunta original (" You need to run this command from the toplevel of the working tree")
VonC
17

Eu tive um problema semelhante, mas me pintei de canto com as ferramentas da GUI.

Eu tinha um subprojeto com alguns arquivos que até agora copiava em vez de fazer o check-in no seu próprio repositório git. Eu criei um repositório na subpasta, fui capaz de confirmar, enviar, etc, muito bem. Mas no repositório pai, a subpasta não foi tratada como um submódulo e seus arquivos ainda estavam sendo rastreados pelo repositório pai - nada bom.

Para sair dessa bagunça, eu precisava dizer ao Git para parar de rastrear a subpasta (sem excluir os arquivos):

proj> git rm -r --cached ./ui/jslib

Então eu tive que dizer que havia um submódulo lá (o que você não pode fazer se algo estiver sendo rastreado pelo git):

proj> git submodule add ./ui/jslib

Atualizar

A maneira ideal de lidar com isso envolve mais algumas etapas. Idealmente, o repositório existente é movido para seu próprio diretório, livre de qualquer módulo pai git, confirmado e enviado por push e, em seguida, adicionado como um submódulo como:

proj> git submodule add [email protected]:user/jslib.git ui/jslib

Isso clonará o repositório git como um submódulo - que envolve as etapas de clonagem padrão, mas também várias outras etapas de configuração mais obscuras que o git executa em seu nome para fazer com que o submódulo funcione. A diferença mais importante é que ele coloca um arquivo .git simples lá, em vez de um diretório .git, que contém uma referência de caminho para onde o diretório git real vive - geralmente na raiz do projeto pai .git / modules / jslib.

Se você não fizer as coisas dessa maneira, elas funcionarão bem para você, mas assim que você comprometer e pressionar os pais, e outro desenvolvedor for puxá-los, você apenas tornará a vida deles muito mais difícil. Será muito difícil para eles replicar a estrutura que você possui em sua máquina, desde que você tenha um diretório .git completo em uma subpasta de um diretório que contenha seu próprio diretório .git.

Portanto, mover, pressionar, git add submódulo, é a opção mais limpa.

Chris Moschini
fonte
16

Para aqueles de vocês que compartilham meu gosto estranho de editar manualmente os arquivos de configuração, adicionar (ou modificar) o seguinte também ajudaria.

.git / config (configuração pessoal)

[submodule "cookbooks/apt"]
    url = https://github.com/opscode-cookbooks/apt

.gitmodules (configuração compartilhada confirmada)

[submodule "cookbooks/apt"]
    path = cookbooks/apt
    url = https://github.com/opscode-cookbooks/apt

Veja isso também - diferença entre .gitmodules e especificação de submódulos em .git / config?

yoniLavi
fonte
2

script bash de uma linha para ajudar a resposta de Chris acima, já que eu havia me pintado em um canto também usando as atualizações do Vundle nos meus scripts .vim. DESTé o caminho para o diretório que contém seus submódulos. Faça isso depois de fazergit rm -r $DEST

DEST='path'; for file in `ls ${DEST}`; do git submodule add `grep url ${DEST}/${file}/.git/config|awk -F= '{print $2}'` ${DEST}/${file}; done

Felicidades

Rick R
fonte