Diviser le grand dépôt Git en plusieurs plus petits

après avoir converti avec succès un dépôt SVN en git, j'ai maintenant un très grand dépôt Git que je veux décomposer en plusieurs dépôts plus petits et maintenir l'histoire.

alors, quelqu'un peut-il aider à briser une pension qui pourrait ressembler à ceci:

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

dans deux dépôts qui ressemblent à ceci:

MyABRepo/
   .git
   DIR_A/
   DIR_B/

My12Repo/
   .git
   DIR_1/
   DIR_2/

j'ai essayé de suivre les directions dans cette question précédente, mais il n'est pas vraiment convient lorsque vous essayez de mettre plusieurs répertoires dans un rapport séparé ( Detach (move) subdirectory dans le dépôt git séparé ).

79
demandé sur Community 2010-10-12 02:32:57

5 réponses

cela va configurer MyABRepo; vous pouvez faire My12Repo de la même façon 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 reste. Vous pouvez supprimer cela avec:

cd ..
git clone MyABRepo.tmp MyABRepo

si tout s'est bien passé, vous pouvez alors enlever MyABRepo.tmp.


Si pour une raison quelconque, vous obtenez un message d'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 de l'utilisation /tmp/git-réécriture.tmp en tant que répertoire temporaire, au lieu de .git-rewrite . Naturellement, vous pouvez substituer n'importe quel chemin que vous voulez au lieu de /tmp/git-rewrite.tmp , tant que vous avez la permission d'écrire, et que le répertoire n'existe pas déjà.

74
répondu unutbu 2010-10-20 19:59:58

vous pouvez utiliser git filter-branch --index-filter avec git rm --cached pour supprimer les répertoires indésirables des clones/copies de votre dépôt original.

par exemple:

trim_repo() { : trim_repo src dst dir-to-trim-out...
  : uses printf %q: needs bash, zsh, or maybe ksh
  git clone "" "" &&
  (
    cd "" &&
    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

vous devrez supprimer manuellement les branches ou les étiquettes non nécessaires de chaque dépôt (par exemple, si vous aviez une branche -X-for-AB , vous voudrez probablement supprimer cela du dépôt" 12").

9
répondu Chris Johnsen 2010-10-12 00:01:51

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

3
répondu EnabrenTane 2012-12-19 22:26:06

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

transforment les répertoires git en leurs propres dépôts dans leur propre emplacement. Pas de sous-arbre drôle d'affaires. Ce script prendra un répertoire existant dans votre dépôt git et le transformera en un dépôt indépendant. En cours de route, il copiera sur l'ensemble de l'histoire du changement répertoire que vous avez fourni.

./git_split.sh <src_repo> <src_branch> <relative_dir_path> <dest_repo>
        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.
3
répondu vangorra 2016-01-06 02:45:06

Merci pour vos réponses mais j'ai fini par copier le dépôt deux fois puis supprimer les fichiers que je ne voulais pas de chacun. Je vais utiliser la branche filter à une date ultérieure pour supprimer toutes les propagations pour les fichiers supprimés car ils sont déjà contrôlés ailleurs.

cp -R MyHugeRepo MyABRepo
cp -R MyHugeRepo My12Repo

cd MyABRepo/
rm -Rf DIR_1/ DIR_2/
git add -A
git commit -a

ça a marché pour ce dont j'avais besoin.

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

0
répondu MikeM 2010-10-20 19:17:10