Digamos que eu tenho uma configuração que se parece com
phd/code/
phd/figures/
phd/thesis/
Por razões históricas, todos eles têm seus próprios repositórios git. Mas eu gostaria de combiná-los em um único para simplificar um pouco as coisas. Por exemplo, agora eu posso fazer dois conjuntos de alterações e ter que fazer algo como
cd phd/code
git commit
cd ../figures
git commit
Seria (agora) bom apenas executar
cd phd
git commit
Parece haver algumas maneiras de fazer isso usando sub-módulos ou retirando dos meus sub-repositórios, mas isso é um pouco mais complexo do que estou procurando. No mínimo, eu ficaria feliz com
cd phd
git init
git add [[everything that's already in my other repositories]]
mas isso não parece uma linha. Existe algo git
que possa me ajudar?
Respostas:
Aqui está uma solução que eu dei aqui :
Primeiro, faça um backup completo do seu diretório phd: não quero ser responsabilizado pela perda de anos de trabalho duro! ;-)
Mova o conteúdo de
phd/code
paraphd/code/code
e corrija o histórico para que pareça que ele sempre esteve lá (isso usa o comando filter-branch do git ):O mesmo para o conteúdo de
phd/figures
ephd/thesis
(basta substituircode
porfigures
ethesis
).Agora sua estrutura de diretórios deve ficar assim:
Em seguida, crie um repositório git no diretório raiz, coloque tudo nele e remova os repositórios antigos:
Finalmente, agora você deve ter o que queria:
Um lado bom desse procedimento é que ele deixará arquivos e diretórios sem versão .
Espero que isto ajude.
Apenas uma palavra de aviso: se seu
code
diretório já possui umcode
subdiretório ou arquivo, as coisas podem dar muito errado (o mesmo parafigures
e, éthesis
claro). Se for esse o caso, basta renomear esse diretório ou arquivo antes de executar todo este procedimento:E quando o procedimento for concluído, adicione esta etapa final:
Obviamente, se o
code
subdiretório ou arquivo não tiver versão, use emmv
vez degit mv
e esqueça osgit commit
s.fonte
mv "$GIT_INDEX_FILE.new" "$GIT_INDEX_FILE"' HEAD
e depois funcionou muito bem!fonte
Talvez, simplesmente (da mesma forma que a resposta anterior, mas usando comandos mais simples), faça de cada um dos repositórios antigos separados um commit que move o conteúdo para um subdiretador chamado adequadamente, por exemplo:
e depois mesclar os três repositórios separados em um novo, fazendo o seguinte:
Então você salvará suas histórias, mas continuará com um único repositório.
fonte
Você pode tentar a estratégia de mesclagem de subárvore . Isso permitirá que você mescle o repositório B no repositório A. A vantagem
git-filter-branch
é que não exige que você reescreva seu histórico do repositório A (quebrando as somas SHA1).fonte
A solução git-filter-branch funciona bem, mas observe que se o seu repositório git vier de uma importação SVN, poderá falhar com uma mensagem como:
Nesse caso, você precisa excluir a revisão inicial da ramificação do filtro - ou seja, alterar
HEAD
no final para[SHA of 2nd revision]..HEAD
- consulte:http://www.git.code-experiments.com/blog/2010/03/merging-git-repositories.html
fonte
A solução @MiniQuark me ajudou muito, mas infelizmente não leva em consideração as tags que estão nos repositórios de origem (pelo menos no meu caso). Abaixo está a minha melhoria na resposta @MiniQuark.
Primeiro crie um diretório que conterá repositórios compostos e repositórios mesclados, crie um diretório para cada um deles.
Faça um pull de cada repositório e busque todas as tags. (Apresentando instruções apenas para o
code
subdiretório)(Isso é aprimoramento no ponto 2 da resposta do MiniQuark) Mova o conteúdo de
new_phd/code
paranew_phd/code/code
e adicione ocode_
prefixo antes de cada tagDepois de fazer isso, haverá duas vezes mais tags do que antes de fazer o branch-filter. Tags antigas permanecem no repositório e novas tags com
code_
prefixo são adicionadas.Remova as tags antigas manualmente:
Repita o ponto 2,3,4 para outros subdiretórios
Agora, temos a estrutura de diretórios como no ponto 3 do @MiniQuark anwser.
Faça como no ponto 4 do analisador MiniQuark, mas depois de fazer um pull e antes de remover o
.git
dir, busque as tags:Continuar..
Esta é apenas outra solução. Espero que ajude alguém, me ajudou :)
fonte
git-stitch-repo da resposta de Aristóteles Pagaltzis ' funciona apenas para repositórios com história simples e linear.
A resposta do MiniQuark funciona para todos os repositórios, mas não trata de tags e ramificações.
Criei um programa que funciona da mesma maneira que o MiniQuark descreve, mas ele usa uma confirmação de mesclagem (com N pais) e também recria todas as tags e ramificações para apontar para essas confirmações de mesclagem.
Veja o repositório git-merge-repos para exemplos de como usá-lo.
fonte
Eu criei uma ferramenta que faz essa tarefa. O método usado é semelhante (faça internamente algumas coisas como --filter-branch), mas é mais amigável. É GPL 2.0
http://github.com/geppo12/GitCombineRepo
fonte
Na verdade, o git-stitch-repo agora suporta ramificações e tags, incluindo tags anotadas (descobri que havia um bug que relatei e ele foi corrigido). O que eu achei útil é com tags. Como as tags são anexadas às confirmações, e algumas das soluções (como a abordagem de Eric Lee) não conseguem lidar com as tags. Você tenta criar uma ramificação de uma marca importada e ela desfaz qualquer fusão / movimentação do git e o envia de volta como se o repositório consolidado fosse quase idêntico ao repositório de onde a marca veio. Além disso, existem problemas se você usar a mesma tag em vários repositórios que você 'mesclou / consolidou'. Por exemplo, se você tiver um anúncio A do repositório B, ambos com a tag rel_1.0. Você mescla o repositório A e o repositório B no repositório AB. Como as tags rel_1.0 têm duas confirmações diferentes (uma para A e outra para B), qual tag será visível na AB? A tag do repositório importado A ou do repositório importado B, mas não os dois.
O git-stitch-repo ajuda a resolver esse problema criando tags rel_1.0-A e rel_1.0-B. Você pode não conseguir fazer check-out da tag rel_1.0 e esperar as duas, mas pelo menos pode vê-las e, teoricamente, pode mesclá-las em uma ramificação local comum e criar uma tag rel_1.0 nessa ramificação mesclada (supondo que você mesclar e não alterar o código-fonte). É melhor trabalhar com ramificações, pois você pode mesclar ramificações de cada repositório em ramificações locais. (o dev-a e o dev-b podem ser mesclados em uma ramificação local do dev que pode ser empurrada para a origem).
fonte
A sequência que você sugeriu
funcionará, mas você perderá seu histórico de consolidação.
fonte
Para mesclar um secondProject em um mainProject:
A) No segundo projeto
B) No projeto principal:
Nesse ramo, faça todas as transformações pesadas que você precisa fazer e as comprometa.
C) Depois, de volta ao mestre e uma fusão clássica entre os dois ramos:
fonte
Vou jogar minha solução aqui também. É basicamente um wrapper de script bash bastante simples
git filter-branch
. Como outras soluções, ele migra apenas ramificações principais e não migra tags. Mas o histórico completo de commit mestre é migrado e é um script bash curto, portanto deve ser relativamente fácil para os usuários revisarem ou ajustarem.https://github.com/Oakleon/git-join-repos
fonte
Esse script bash soluciona o problema de caractere da guia sed (no MacOS, por exemplo) e o problema de arquivos ausentes.
Esta é uma combinação dos posts de miniquark , marius-butuc e ryan . Um brinde a eles!
fonte