Diviser le grand repository Git en plusieurs plus petits

Après avoir converti avec succès un référentiel SVN en Git, j’ai maintenant un très grand référentiel Git que je souhaite décomposer en plusieurs repositorys plus petits et en conserver l’historique.

Ainsi, quelqu’un peut-il aider à briser un repo qui pourrait ressembler à ceci:

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

Dans deux référentiels qui ressemblent à ceci:

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

J’ai essayé de suivre les instructions dans cette question précédente, mais cela ne convient pas vraiment lorsque vous essayez de placer plusieurs répertoires dans un référentiel séparé (sous-répertoire Détacher (déplacer) dans un référentiel Git distinct ).

Cela va configurer MyABRepo; vous pouvez également faire My12Repo bien sûr.

 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 

Une référence à .git / refs / original / refs / heads / master rest. Vous pouvez supprimer cela avec:

 cd .. git clone MyABRepo.tmp MyABRepo 

Si tout s’est bien passé, vous pouvez alors supprimer MyABRepo.tmp.


Si pour une raison quelconque vous obtenez une erreur concernant .git-rewrite, vous pouvez essayer ceci:

 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 

Cela créera et utilisera /tmp/git-rewrite.tmp comme répertoire temporaire, au lieu de .git-rewrite . Naturellement, vous pouvez remplacer n’importe quel chemin que vous souhaitez au lieu de /tmp/git-rewrite.tmp , à condition que vous ayez l’autorisation d’écriture et que le répertoire n’existe pas déjà.

Vous pouvez utiliser git filter-branch --index-filter avec git rm --cached pour supprimer les répertoires indésirables des clones / copies de votre référentiel d’origine.

Par exemple:

 sortingm_repo() { : sortingm_repo src dst dir-to-sortingm-out... : uses printf %q: needs bash, zsh, or maybe ksh git clone "$1" "$2" && ( cd "$2" && shift 2 && : mirror original twigs && 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 ) } sortingm_repo MyHugeRepo MyABRepo DIR_1 DIR_2 sortingm_repo MyHugeRepo My12Repo DIR_A DIR_B 

Vous devrez supprimer manuellement les twigs ou balises inutiles de chaque référentiel (par exemple, si vous aviez une twig feature-x-for-AB , vous souhaiterez probablement la supprimer du référentiel «12»).

Voici un script ruby ​​qui le fera. https://gist.github.com/4341033

Le projet git_split est un script simple qui fait exactement ce que vous recherchez. https://github.com/vangorra/git_split

Transformez les répertoires git en leurs propres référentiels dans leur propre emplacement. Aucune entreprise drôle de sous-arbre. Ce script utilisera un répertoire existant dans votre repository git et transformera ce répertoire en un référentiel indépendant. En cours de route, il copiera tout l’historique des modifications du répertoire que vous avez fourni.

 ./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. 

Merci pour vos réponses mais j’ai fini par copier deux fois le repository puis supprimer les fichiers que je ne voulais pas de chacun. Je vais utiliser la twig de filtrage à une date ultérieure pour supprimer tous les commits pour les fichiers supprimés car ils sont déjà contrôlés par des versions ailleurs.

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

Cela a fonctionné pour ce dont j’avais besoin.

EDIT: Bien sûr, la même chose a été faite dans le My12Repo contre le répertoire A et B. Cela m’a donné deux repos avec une histoire identique jusqu’au point où j’ai supprimé les répertoires indésirables.