큰 Git 저장소를 여러 개의 작은 저장소로 분할 같은 repo를

SVN 리포지토리를 Git으로 성공적으로 변환 한 후 이제 여러 개의 작은 리포지토리로 나누고 기록을 유지하려는 매우 큰 Git 리포지토리를 갖게되었습니다.

따라서 누군가 다음과 같은 repo를 분해하는 데 도움을 줄 수 있습니까?

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

다음과 같은 두 개의 저장소로 :

MyABRepo/
   .git
   DIR_A/
   DIR_B/

My12Repo/
   .git
   DIR_1/
   DIR_2/

이 이전 질문에서 지침을 따르려고 시도했지만 여러 디렉토리를 별도의 저장소에 넣으려고 할 때 실제로 적합하지 않습니다 ( Detach (move) 하위 디렉토리를 별도의 Git 저장소로 ).



답변

그러면 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 / heads / 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쓰기 권한이 있고 디렉토리가 아직 존재하지 않는 한 대신 원하는 경로로 대체 할 수 있습니다.


답변

git filter-branch --index-filterwith 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”저장소에서 삭제할 수 있음).


답변

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.


답변

다음은이를 수행 할 루비 스크립트입니다.
https://gist.github.com/4341033


답변

귀하의 답변에 감사하지만 저장소를 두 번 복사 한 다음 각각에서 원하지 않는 파일을 삭제했습니다. 나중에 다른 곳에서 버전이 제어되기 때문에 삭제 된 파일에 대한 모든 커밋을 제거하기 위해 나중에 filter-branch를 사용할 것입니다.

cp -R MyHugeRepo MyABRepo
cp -R MyHugeRepo My12Repo

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

이것은 내가 필요한 것을 위해 일했습니다.

편집 : 물론 A 및 B 디렉토리에 대해 My12Repo에서 동일한 작업이 수행되었습니다. 이것은 원치 않는 디렉토리를 삭제할 때까지 동일한 기록을 가진 두 개의 저장소를 제공했습니다.


답변