Dividir grande repository Git em muitos repositorys menores

Depois de converter com sucesso um repository SVN para o Git, agora tenho um repository Git muito grande que quero dividir em vários repositorys menores e manter o histórico.

Então, alguém pode ajudar a dividir um repo que pode ser assim:

MyHugeRepo/ .git/ DIR_A/ DIR_B/ DIR_1/ DIR_2/ 

Em dois repositorys que se parecem com isto:

 MyABRepo/ .git DIR_A/ DIR_B/ My12Repo/ .git DIR_1/ DIR_2/ 

Eu tentei seguir as instruções desta pergunta anterior, mas isso não se encheckbox ao tentar colocar vários diretórios em um repository separado ( Detach (move) subdiretório em repository Git separado ).

Isso irá configurar o MyABRepo; você pode fazer o My12Repo da mesma forma, é claro.

 git clone MyHugeRepo/ MyABRepo.tmp/ cd MyABRepo.tmp git filter-branch --prune-empty --index-filter 'git rm --cached --ignore-unmatch DIR_1/* DIR_2/*' HEAD 

Uma referência a .git / refs / original / refs / heads / master permanece. Você pode remover isso com:

 cd .. git clone MyABRepo.tmp MyABRepo 

Se tudo correu bem, você pode então remover MyABRepo.tmp.


Se, por algum motivo, você receber um erro referente a .git-rewrite, tente isto:

 git clone MyHugeRepo/ MyABRepo.tmp/ cd MyABRepo.tmp git filter-branch -d /tmp/git-rewrite.tmp --prune-empty --index-filter 'git rm --cached --ignore-unmatch DIR_1/* DIR_2/*' HEAD cd .. git clone MyABRepo.tmp MyABRepo 

Isso criará e usará /tmp/git-rewrite.tmp como um diretório temporário, em vez de .git-rewrite . Naturalmente, você pode replace qualquer caminho que desejar em vez de /tmp/git-rewrite.tmp , desde que você tenha permissão de gravação e o diretório ainda não exista.

Você poderia usar git filter-branch --index-filter com git rm --cached para excluir os diretórios indesejados dos clones / cópias de seu repository original.

Por exemplo:

 trim_repo() { : trim_repo src dst dir-to-trim-out... : uses printf %q: needs bash, zsh, or maybe ksh git clone "$1" "$2" && ( cd "$2" && shift 2 && : mirror original branches && git checkout HEAD~0 2>/dev/null && d=$(printf ' %q' "$@") && git for-each-ref --shell --format=' o=%(refname:short) b=${o#origin/} && if test -n "$b" && test "$b" != HEAD; then git branch --force --no-track "$b" "$o" fi ' refs/remotes/origin/ | sh -e && git checkout - && git remote rm origin && : do the filtering && git filter-branch \ --index-filter 'git rm --ignore-unmatch --cached -r -- '"$d" \ --tag-name-filter cat \ --prune-empty \ -- --all ) } trim_repo MyHugeRepo MyABRepo DIR_1 DIR_2 trim_repo MyHugeRepo My12Repo DIR_A DIR_B 

Você precisará excluir manualmente as ramificações ou tags desnecessárias de cada repository (por exemplo, se você tiver uma ramificação feature-x-for-AB , provavelmente desejará excluí-la do repository “12”).

Aqui está um script de ruby que fará isso. https://gist.github.com/4341033

O projeto git_split é um script simples que faz exatamente o que você está procurando. https://github.com/vangorra/git_split

Transforme os diretórios git em seus próprios repositorys em seu próprio local. Nenhum subtree negócio engraçado. Este script pegará um diretório existente em seu repository git e transformará esse diretório em um repository independente. Ao longo do caminho, ele copiará todo o histórico de alterações do diretório fornecido.

 ./git_split.sh     src_repo - The source repo to pull from. src_branch - The branch of the source repo to pull from. (usually master) relative_dir_path - Relative path of the directory in the source repo to split. dest_repo - The repo to push to. 

Obrigado por suas respostas, mas acabei copiando o repository duas vezes e depois excluindo os arquivos que eu não queria de cada um. Eu vou usar o ramo de filtro em uma data posterior para remover todos os commits dos arquivos excluídos, já que eles já são controlados por versão em outro lugar.

 cp -R MyHugeRepo MyABRepo cp -R MyHugeRepo My12Repo cd MyABRepo/ rm -Rf DIR_1/ DIR_2/ git add -A git commit -a 

Isso funcionou para o que eu precisava.

EDIT: Claro, a mesma coisa foi feita no My12Repo contra o diretório A e B. Isso me deu dois repos com histórico idêntico até o ponto em que apaguei os diretórios indesejados.