Разделите большой Git-репозиторий на множество более мелких - PullRequest
84 голосов
/ 12 октября 2010

После успешного преобразования SVN-репозитория в Git у меня теперь есть очень большой Git-репозиторий, который я хочу разбить на несколько небольших репозиториев и вести историю.

Итак, кто-то может помочь с разрушением репо, которое может выглядеть так:

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

В два хранилища, которые выглядят так:

MyABRepo/
   .git
   DIR_A/
   DIR_B/

My12Repo/
   .git
   DIR_1/
   DIR_2/

Я пробовал следовать инструкциям в этом предыдущем вопросе, но он не очень подходит при попытке поместить несколько каталогов в отдельный репозиторий ( Отделить (переместить) подкаталог в отдельный репозиторий Git ).

Ответы [ 5 ]

78 голосов
/ 12 октября 2010

Это настроит MyABRepo;Конечно, вы можете сделать My12Repo аналогично.

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 

Ссылка на .git / refs / original / refs /head / master остается.Вы можете удалить это с помощью:

cd ..
git clone MyABRepo.tmp MyABRepo

Если все прошло хорошо, вы можете удалить MyABRepo.tmp.


Если по какой-либо причине вы получаете сообщение об ошибке .git-rewrite, вы можете попробовать это:

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

Это создаст и использует /tmp/git-rewrite.tmp в качестве временного каталога вместо .git-rewrite.Естественно, вы можете заменить любой путь по своему желанию вместо /tmp/git-rewrite.tmp, если у вас есть разрешение на запись, а каталог еще не существует.

10 голосов
/ 12 октября 2010

Вы можете использовать git filter-branch --index-filter с git rm --cached для удаления ненужных каталогов из клонов / копий вашего исходного хранилища.

Например:

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

Вам потребуется вручнуюудалите ненужные ветви или теги каждого репозитория (например, если у вас была ветка feature-x-for-AB , то вы, вероятно, хотите удалить ее из репозитория «12»).

5 голосов
/ 06 января 2016

Проект git_split - это простой скрипт, который делает именно то, что вы ищете.https://github.com/vangorra/git_split

Превратите каталоги git в свои собственные репозитории в их собственном местоположении.Не поддельное смешное дело.Этот скрипт возьмет существующий каталог в вашем git-репозитории и превратит этот каталог в независимый собственный репозиторий.Попутно он скопирует всю историю изменений для предоставленного вами каталога.

./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.
4 голосов
/ 20 декабря 2012

Вот скрипт ruby, который сделает это.https://gist.github.com/4341033

1 голос
/ 20 октября 2010

Спасибо за ваши ответы, но я просто дважды скопировал хранилище, а затем удалил файлы, которые мне не нужны. Я собираюсь использовать ветвь фильтра позже, чтобы убрать все коммиты для удаленных файлов, поскольку они уже контролируются версией в другом месте.

cp -R MyHugeRepo MyABRepo
cp -R MyHugeRepo My12Repo

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

Это сработало для того, что мне было нужно.

РЕДАКТИРОВАТЬ: Конечно, то же самое было сделано в My12Repo против каталога A и B. Это дало мне два репозитория с одинаковой историей до того момента, когда я удалил ненужные каталоги.

...