Eu preciso mesclar dois repositórios Git em um novo repositório, terceiro. Eu encontrei muitas descrições de como fazer isso usando uma mesclagem de subárvore (por exemplo, a resposta de Jakub Narębski em Como você mescla dois repositórios Git? ) E seguir essas instruções geralmente funciona, exceto que, quando eu submeto a subárvore, mesclamos todos os arquivos dos repositórios antigos são registrados como novos arquivos adicionados. Eu posso ver o histórico de confirmação dos repositórios antigos quando o faço git log
, mas se o fizer git log <file>
, mostrará apenas uma confirmação para esse arquivo - a mesclagem da subárvore. A julgar pelos comentários na resposta acima, não estou sozinho vendo esse problema, mas não encontrei soluções publicadas para ele.
Existe alguma maneira de mesclar repositórios e deixar intacto o histórico de arquivos individuais?
fonte
Respostas:
Acontece que a resposta é muito mais simples se você estiver simplesmente tentando colar dois repositórios e parecer que era assim o tempo todo, em vez de gerenciar uma dependência externa. Você só precisa adicionar controles remotos aos seus repositórios antigos, mesclá-los ao seu novo mestre, mover os arquivos e pastas para um subdiretório, confirmar a movimentação e repetir para todos os repositórios adicionais. Sub-módulos, mesclagens de sub-árvores e rebotes sofisticados destinam-se a resolver um problema ligeiramente diferente e não são adequados para o que eu estava tentando fazer.
Aqui está um exemplo de script do Powershell para colar dois repositórios:
Obviamente, você pode mesclar old_b em old_a (que se torna o novo repositório combinado) se preferir fazer isso - modifique o script para se adequar.
Se você deseja trazer ramificações de recursos em andamento também, use o seguinte:
Essa é a única parte não óbvia do processo - não é uma mesclagem de subárvore, mas um argumento para a mesclagem recursiva normal que informa ao Git que renomeamos o alvo e ajuda o Git a alinhar tudo corretamente.
Eu escrevi uma explicação um pouco mais detalhada aqui .
fonte
git mv
não funciona tão bem. quando você usagit log
um dos arquivos movidos posteriormente, você obtém apenas a confirmação da movimentação. toda a história anterior está perdida. isso é porquegit mv
é realmente,git rm; git add
mas em uma etapa .git log --follow
, ou todas as ferramentas da GUI fazem isso automaticamente. Com uma mesclagem de subárvore, você não pode obter o histórico de arquivos individuais, tanto quanto eu sei, portanto esse método é melhor.1
(o número um) parals
e 'olho' maiúsculo paraxargs
. Obrigado por esta dica!Aqui está uma maneira de não reescrever nenhum histórico, para que todos os IDs de confirmação permaneçam válidos. O resultado final é que os arquivos do segundo repositório acabarão em um subdiretório.
Adicione o segundo repositório como um controle remoto:
Verifique se você baixou todos os commits do secondrepo:
Crie uma ramificação local a partir da ramificação do segundo repositório:
Mova todos os seus arquivos para um subdiretório:
Mesclar a segunda ramificação na ramificação principal do primeiro repositório:
Seu repositório terá mais de uma confirmação raiz, mas isso não deve representar um problema.
fonte
git remote show secondrepo
--allow-unrelated-histories
. Veja o histórico desta resposta.Alguns anos se passaram e há soluções bem votadas bem fundamentadas, mas quero compartilhar as minhas porque era um pouco diferente, porque eu queria mesclar 2 repositórios remotos em um novo, sem excluir o histórico dos repositórios anteriores.
Crie um novo repositório no Github.
Faça o download do repositório recém-criado e adicione o repositório remoto antigo.
Busque todos os arquivos do repositório antigo para que uma nova ramificação seja criada.
Na ramificação mestre, faça uma mesclagem para combinar o repositório antigo com o recém-criado.
Crie uma nova pasta para armazenar todo o novo conteúdo criado que foi adicionado no OldRepo e mover seus arquivos para essa nova pasta.
Por fim, você pode fazer o upload dos arquivos dos repositórios combinados e excluir com segurança o OldRepo do GitHub.
Espero que isso possa ser útil para quem lida com a fusão de repositórios remotos.
fonte
git remote rm OldRepo
.por favor, dê uma olhada no uso
para ligar duas histórias no início de suas vidas.
Se você tiver caminhos sobrepostos, corrija-os com
ao usar o log, verifique se "encontra cópias mais difíceis" com
Dessa forma, você encontrará movimentos de arquivos no caminho.
fonte
Eu transformei a solução do @Flimm em um
git alias
assim (adicionado ao meu~/.gitconfig
):fonte
$GIT_PREFIX
?Esta função clonará o repositório remoto no diretório de repositório local:
Como usar:
Aviso prévio. Esse script pode reescrever confirmações, mas salvará todos os autores e datas, significa que novas confirmações terão outros hashes, e se você tentar enviar alterações para o servidor remoto, ele poderá ser capaz apenas com a força de chave, e também reescreverá confirmações no servidor. Portanto, faça backups antes do lançamento.
Lucro!
fonte
git filter-branch --index-filter
trabalhar. Normalmente, recebo uma mensagem de erro informando que o arquivo de índice .new não existe. Isso soa sinos?git-add-repo.sh
com a função acima, no final do arquivo coloque esta linhagit-add-repo "$@"
. Depois disso, você pode usá-lo a partir do zsh comocd current/git/package
ebash path/to/git-add-repo.sh https://github.com/example/example dir/to/save
mv "$GIT_INDEX_FILE.new" "$GIT_INDEX_FILE"
falha às vezes, então você deve adicionar umif test
.Siga as etapas para incorporar um repositório em outro repositório, tendo um único histórico git mesclando os dois históricos git.
my/new/subdir
(3 ocorrências) pela estrutura de diretórios na qual você deseja que o repo filho seja executado.Se você verificar o log do git no repositório pai agora, ele deverá fazer com que o repositório filho confirme a fusão. Você também pode ver a tag indicando na fonte de confirmação.
O artigo abaixo me ajudou a incorporar um repositório em outro repositório, tendo um único histórico do git ao mesclar os dois.
http://ericlathrop.com/2014/01/combining-git-repositories/
Espero que isto ajude. Feliz codificação!
fonte
git filter-branch --prune-empty --tree-filter ' if [ ! -e my/new/subdir ]; then mkdir -p my/new/subdir; git ls-tree --name-only $GIT_COMMIT | xargs -I files mv files my/new/subdir; fi'
Digamos que você deseja mesclar repositório
a
parab
(eu estou supondo que eles estão localizados ao lado do outro):Caso queira colocar
a
em um subdiretório, faça o seguinte antes dos comandos acima:Para isso, você precisa
git-filter-repo
instalar (filter-branch
é desencorajado ).Um exemplo de mesclagem de 2 grandes repositórios, colocando um deles em um subdiretório: https://gist.github.com/x-yuri/9890ab1079cf4357d6f269d073fd9731
Mais sobre isso aqui .
fonte