Eu tenho um repositório Git em uma pasta chamada XXX e eu tenho um segundo repositório Git chamado YYY .
Desejo importar o repositório XXX para o repositório YYY como um subdiretório chamado ZZZ e adicionar todo o histórico de alterações do XXX ao YYY .
Estrutura da pasta antes:
├── XXX
│ ├── .git
│ └── (project files)
└── YYY
├── .git
└── (project files)
Estrutura de pastas após:
YYY
├── .git <-- This now contains the change history from XXX
├── ZZZ <-- This was originally XXX
│ └── (project files)
└── (project files)
Isso pode ser feito ou devo recorrer ao uso de submódulos?
Respostas:
Provavelmente, a maneira mais simples seria colocar o material XXX em uma ramificação no AAAA e mesclar no master:
Em AAA :
Na verdade, eu apenas tentei isso com alguns dos meus repositórios e funciona. Diferentemente da resposta de Jörg, ele não permitirá que você continue usando o outro repositório, mas acho que você não especificou isso.
Nota: Como isso foi originalmente escrito em 2009, o git adicionou a mesclagem de subárvore mencionada na resposta abaixo. Eu provavelmente usaria esse método hoje, embora, é claro, esse método ainda funcione.
fonte
git mv $(ls|grep -v <your foldername>) <your foldername>/
Isso copiará todos os arquivos e pastas para a nova pastaSe você deseja manter o histórico exato de confirmação do segundo repositório e, portanto, também mantém a capacidade de mesclar facilmente as alterações upstream no futuro, eis o método que você deseja. Isso resulta no histórico não modificado da subárvore sendo importada para seu repositório, mais uma confirmação de mesclagem para mover o repositório mesclado para o subdiretório.
Você pode acompanhar as alterações upstream da seguinte maneira:
O Git descobre por si próprio onde estão as raízes antes de fazer a mesclagem, para que você não precise especificar o prefixo nas mesclagens subsequentes.
A desvantagem é que, no histórico mesclado, os arquivos não têm prefixo (não estão em um subdiretório). Como resultado
git log ZZZ/a
, todas as alterações serão exibidas (se houver), exceto aquelas no histórico mesclado. Você pode fazer:mas isso não mostrará as alterações além do histórico mesclado.
Em outras palavras, se você não alterar
ZZZ
os arquivos no repositórioXXX
, precisará especificar--follow
um caminho sem prefixo. Se você os alterar nos dois repositórios, terá 2 comandos, nenhum dos quais mostra todas as alterações.Versões Git anteriores à 2.9 : você não precisa passar a
--allow-unrelated-histories
opção paragit merge
.O método na outra resposta que usa
read-tree
e pula amerge -s ours
etapa não é diferente de copiar os arquivos com cp e confirmar o resultado.A fonte original era do artigo de ajuda "Subtree Merge" do github . E outro link útil .
fonte
git log
dos arquivos que eu puxei, apenas vejo a mesclagem única ser confirmada e nada da sua vida anterior no outro repositório? Git 1.8.0git log -- myfile
em vez degit log -- rack/myfile
--allow-unrelated-histories
ao fazer a mesclagem.git-subtree
é um script projetado para exatamente esse caso de uso de mesclar vários repositórios em um, preservando o histórico (e / ou dividindo o histórico de subárvores, embora isso pareça irrelevante para esta pergunta). Ele é distribuído como parte da árvore git desde a liberação 1.7.11 .Para mesclar um repositório
<repo>
na revisão<rev>
como subdiretório<prefix>
, usegit subtree add
o seguinte:O git-subtree implementa a estratégia de mesclagem de subárvore de uma maneira mais amigável.
Para o seu caso, dentro do repositório YYY, você executaria:
A desvantagem é que, no histórico mesclado, os arquivos não têm prefixo (não estão em um subdiretório). Como resultado
git log ZZZ/a
, todas as alterações serão exibidas (se houver), exceto aquelas no histórico mesclado. Você pode fazer:mas isso não mostrará as alterações além do histórico mesclado.
Em outras palavras, se você não alterar
ZZZ
os arquivos no repositórioXXX
, precisará especificar--follow
um caminho sem prefixo. Se você os alterar nos dois repositórios, terá 2 comandos, nenhum dos quais mostra todas as alterações.Mais sobre isso aqui .
fonte
git subtree add -P name-of-desired-prefix ~/location/of/git/repo-without-.git branch-name
Existe uma instância bem conhecida disso no próprio repositório Git, que é coletivamente conhecido na comunidade Git como " a mesclagem mais legal de todos os tempos " (após o assunto Linus Torvalds usado no e-mail da lista de discussão do Git que descreve esse mesclar). Nesse caso, a
gitk
GUI do Git, que agora faz parte do Git, na verdade costumava ser um projeto separado. Linus conseguiu mesclar esse repositório no repositório Git de uma maneira quegit pull
editadas.O e-mail contém as etapas necessárias para a reprodução, mas não é para os fracos de coração: primeiro, Linus escreveu para o Git, então ele provavelmente sabe um pouco mais sobre isso do que você ou eu, e segundo, isso foi há quase 5 anos e o Git melhorou consideravelmente desde então, então talvez agora seja muito mais fácil.
Em particular, acho que hoje em dia se usaria um submódulo gitk, nesse caso específico.
fonte
git-subtree
ferramenta que pode ajudá-lo com isso: github.com/apenwarr/git-subtreesubtree
estratégia de mesclagem, especialmente em conjunto com agit-subtree
ferramenta, é uma boa alternativa, talvez até superior, aos submódulos.A maneira mais simples de fazer isso é usar o git format-patch.
Suponha que temos 2 repositórios git foo e bar .
foo contém:
bar contém:
e queremos terminar com foo contendo o histórico da barra e esses arquivos:
Então, para fazer isso:
E se queremos reescrever todas as confirmações de mensagens da barra, podemos fazer, por exemplo, no Linux:
Isso adicionará "[bar]" no início de cada mensagem de confirmação.
fonte
git am
provavelmente falhará.[ ]
da mensagem de confirmação. Portanto, você deve usar um marcador diferente de[bar]
Essa função clonará o repo remoto no dir repo local, após a mesclagem de todas as confirmações serem salvas,
git log
serão mostradas as confirmações originais e os caminhos adequados:Como usar:
Se fizer algumas alterações, você pode até mover arquivos / diretórios de repositório mesclado para caminhos diferentes, por exemplo:
Avisos
Caminhos substitui via
sed
, portanto, verifique se ele se moveu nos caminhos adequados após a mesclagem.O
--allow-unrelated-histories
parâmetro existe apenas desde git> = 2.9.fonte
gnu-sed
para que agit-add-repo
função funcione. Mais uma vez obrigado Andrey!Com base neste artigo , o uso da subárvore é o que funcionou para mim e apenas o histórico aplicável foi transferido. Poste aqui caso alguém precise das etapas (substitua os espaços reservados pelos valores aplicáveis a você):
no repositório de origem, divida a subpasta em uma nova ramificação
git subtree split --prefix=<source-path-to-merge> -b subtree-split-result
no repositório de destino mesclado na ramificação de resultados divididos
verifique suas alterações e confirme
Não esqueça de
Limpar excluindo a
subtree-split-result
ramificaçãogit branch -D subtree-split-result
Remova o controle remoto que você adicionou para buscar os dados do repositório de origem
git remote rm merge-source-repo
fonte
Adicionando outra resposta, acho que isso é um pouco mais simples. Um pull de repo_dest é feito em repo_to_import e, em seguida, um push --set-upstream URL: repo_dest master.
Esse método funcionou para mim importando vários repositórios menores para um maior.
Como importar: repo1_to_import para repo_dest
Renomeie ou mova os arquivos e diretórios para a posição desejada no repositório original antes de fazer a importação. por exemplo
O método descrito no link a seguir inspirou essa resposta. Eu gostei, pois parecia mais simples. Mas cuidado! Há dragões! https://help.github.com/articles/importing-an-external-git-repository
git push --mirror url:repo_dest
envia o histórico e o estado do repo local para remoto (url: repo_dest). MAS exclui o histórico antigo e o estado do controle remoto. Segue diversão! : -Efonte
Eu queria importar apenas alguns arquivos do outro repositório (XXX) no meu caso. A subárvore era muito complicada para mim e as outras soluções não funcionaram. Isto é o que eu fiz:
Isso fornece uma lista separada por espaço de todas as confirmações que afetam os arquivos que eu queria importar (ZZZ) na ordem inversa (talvez seja necessário adicionar --follow para capturar renomeados também). Depois fui para o repositório de destino (AAA), adicionei o outro repositório (XXX) como remoto, fiz uma busca a partir dele e, finalmente:
que adiciona todos os commits à sua ramificação, você terá todos os arquivos com o histórico deles e poderá fazer o que quiser com eles, como se eles sempre estivessem neste repositório.
fonte
Veja Exemplo básico no presente artigo e considerar esse mapeamento em repositórios:
A
<->YYY
,B
<->XXX
Após toda a atividade descrita neste capítulo (após a mesclagem), remova a ramificação
B-master
:Em seguida, pressione as alterações.
Funciona para mim.
fonte
Eu estava em uma situação em que estava procurando,
-s theirs
mas é claro que essa estratégia não existe. Minha história era que eu havia bifurcado um projeto no GitHub e, agora, por algum motivo,master
não foi possível mesclar meu local,upstream/master
embora eu não tenha feito alterações locais nesse ramo. (Realmente não sei o que aconteceu lá - acho que a montante tinha feito alguns empurrões sujos nos bastidores, talvez?)O que acabei fazendo foi
Então agora o meu
master
está novamente sincronizadoupstream/master
(e você pode repetir o acima para qualquer outro ramo que também queira sincronizar da mesma forma).fonte
git reset --hard upstream/master
em suamaster
filial local faria o trabalho. Dessa forma, você não perde o conflito de ramificação local - coisas como o upstream padrão.Posso sugerir outra solução (alternativa aos submódulos git ) para o seu problema - ferramenta gil (git links)
Permite descrever e gerenciar dependências complexas de repositórios git.
Também fornece uma solução para o problema de dependência de sub-módulos recursivos do git .
Considere que você possui as seguintes dependências do projeto: exemplo de gráfico de dependência do repositório git
Em seguida, você pode definir o
.gitlinks
arquivo com a descrição da relação dos repositórios:Cada linha descreve o link git no seguinte formato:
Finalmente, você deve atualizar seu repositório de amostras raiz:
Como resultado, você clonará todos os projetos necessários e os vinculará de maneira adequada.
Se você deseja confirmar todas as alterações em algum repositório com todas as alterações em repositórios vinculados a filhos, é possível fazê-lo com um único comando:
Os comandos pull, push funcionam de maneira semelhante:
A ferramenta Gil (git links) suporta os seguintes comandos:
Mais sobre o problema de dependência dos sub-módulos recursivos git .
fonte
Deixe-me usar nomes
a
(no lugar deXXX
eZZZ
) eb
(no lugar deYYY
), pois isso facilita a leitura da descrição.Digamos que você deseja mesclar repositório
a
parab
(eu estou supondo que eles estão localizados ao lado do outro):Para isso, você precisa
git-filter-repo
instalar (filter-branch
é desencorajado ).Um exemplo de mesclagem de 2 repositórios grandes, colocando um deles em um subdiretório: https://gist.github.com/x-yuri/9890ab1079cf4357d6f269d073fd9731
Mais sobre isso aqui .
fonte
Não conheço uma maneira fácil de fazer isso. Você PODE fazer isso:
Posso editar com detalhes, se isso parecer atraente.
fonte
Eu acho que você pode fazer isso usando 'git mv' e 'git pull'.
Eu sou um bom git noob - tenha cuidado com seu repositório principal - mas tentei isso em um diretório temporário e ele parece funcionar.
Primeiro - renomeie a estrutura de XXX para corresponder à aparência que deseja quando estiver dentro de AAAA:
Agora XXX fica assim:
Agora use 'git pull' para buscar as alterações:
Agora YYY é assim:
fonte