Este é um exemplo de estrutura de diretório
ParentRepo/
.git/
parent_file
ChildRepo/
.git/
child_file
child_untracked
Quero que o ParentRepo rastreie as alterações de todos os arquivos sob si mesmo (rastrear parent_file
, child_file
, child_untracked
mas não rastrear ChildRepo/.git
) como se ChildRepo
não fosse um repositório git, mas preciso mantê-lo ChildRepo
como um repositório git
Existem três requisitos rígidos
- O conteúdo do ChildRepo deve ser rastreado diretamente no ParentRepo e não como referência a um commit do ChildRepo. Por exemplo, devo ser capaz de excluir
ChildRepo/
e recuperar seu conteúdo a qualquer momento no histórico do ParentRepo usando apenas informações doParentRepo/.git/
diretório, sem usar uma cópia externa do ChildRepo de outro servidor ou de um backup. Adicionar o ChildRepo como um submódulo do ParentRepo é insuficiente, pois, se todo o diretório do ChildRepo for excluído, não há como recuperá-lo usando apenas as informações do ParentRepo. A recuperaçãoChildRepo/.git/
não é necessária. - O ChildRepo deve permanecer um repositório git que tenha seu próprio histórico de desenvolvimento independente do ParentRepo; não podemos excluir a
ChildRepo/.git/
pasta - O ParentRepo deve ser capaz de rastrear alterações que nunca são confirmadas no ChildRepo, por exemplo,
child_untracked
podem nunca entrar no histórico do ChildRepo, mas ainda deve ser possível rastreá-las no ParentRepo
Atualmente, o git trata qualquer diretório com um subdiretório .git/ como um repositório git e preciso ignorar esse comportamento
Estas são as razões para os estranhos requisitos conflitantes
- Uma compilação completa de qualquer versão anterior deve ser possível, mas não há garantia de que a cópia upstream do ChildRepo esteja disponível no futuro. Se o ChildRepo for removido do ParentRepo no futuro, é possível interromper uma compilação anterior que dependa do ChildRepo, pois o conteúdo não é armazenado no ParentRepo e o upstream foi excluído permanentemente. Quanto ao motivo pelo qual o ChildRepo não pode ser copiado separadamente, não há como garantir que uma cópia do ChildRepo seja armazenada junto com o ParentRepo por todo o período futuro do ParentRepo, e também não há garantia de que a cópia do ChildRepo contenha todos os commits referenciados pelo ParentRepo se, por exemplo, o histórico do ChildRepo tiver sido reescrito. A preservação de compilações anteriores é o objetivo principal e é de extrema importância aqui; portanto, o repositório pai deve rastrear o conteúdo de todas as dependências, não apenas as versões.
- O ChildRepo deve rastrear seu próprio histórico de desenvolvimento independente do ParentRepo
- Nem sempre faz sentido, nem sempre é possível fazer um commit no ChildRepo no momento exato em que preciso fazer um commit no ParentRepo
Descompacte-o como um submódulo com
git rm --cached
e adicione-o novamente como um subdiretório (ou melhor, adicione alguns arquivos individuais) usando ferramentas de baixo nível:Costumava ser possível simplesmente fazer:
O trailing
/
é importante, pois faz com que o conteúdo seja adicionado, e não o repositório. Infelizmente, nas versões atuais do Git, isso parece não funcionar mais.Observe que você não conseguirá adicionar um
.git
subdiretório mesmo se tentar – a exclusão é fixa. (Mas você podegit fetch
ramificar o diretório pai para manter uma cópia local.)