문제

나는 힘내 여러 하위 디렉터리를 포함하는 저장소입니다.이제 하위 디렉터리 중 하나가 다른 디렉터리와 관련이 없으며 별도의 저장소에 분리되어야 한다는 사실을 발견했습니다.

하위 디렉터리 내의 파일 기록을 유지하면서 이 작업을 어떻게 수행할 수 있습니까?

나는 복제본을 만들고 각 복제본의 원하지 않는 부분을 제거할 수 있다고 생각하지만, 이것이 이전 개정판 등을 확인할 때 완전한 트리를 제공할 것이라고 생각합니다.이는 허용될 수 있지만 두 저장소가 공유된 기록을 갖고 있지 않은 척할 수 있는 것을 선호합니다.

명확히 하기 위해 다음과 같은 구조를 가지고 있습니다.

XYZ/
    .git/
    XY1/
    ABC/
    XY2/

그러나 나는 대신 이것을 원합니다:

XYZ/
    .git/
    XY1/
    XY2/
ABC/
    .git/
    ABC/
도움이 되었습니까?

해결책

업데이트:이 프로세스는 매우 일반적이어서 GIT 팀이 새로운 도구로 훨씬 간단하게 만들었습니다. git subtree. 여기를 봐: 별도의 git 저장소로 디렉토리를 분리 (이동) 하위 디렉토리를 분리하십시오


저장소를 복제 한 다음 사용하려고합니다 git filter-branch 새 repo에서 원하는 하위 디렉토리를 제외한 모든 것을 표시하려면 쓰레기 수집이 필요합니다.

  1. 로컬 저장소를 복제하려면 :

    git clone /XYZ /ABC
    

    (참고 : 리포지토리는 하드 링크를 사용하여 복제되지만 하드 링크 파일이 자체적으로 수정되지 않기 때문에 문제가되지 않습니다. 새 파일이 생성됩니다.)

  2. 이제 우리가 다시 쓰고 싶은 흥미로운 가지를 보존 한 다음, 원점을 제거하여 그곳을 밀지 않고 오래된 커밋이 원점에 의해 참조되지 않도록하겠습니다.

    cd /ABC
    for i in branch1 br2 br3; do git branch -t $i origin/$i; done
    git remote rm origin
    

    또는 모든 원격 브랜치의 경우 :

    cd /ABC
    for i in $(git branch -r | sed "s/.*origin\///"); do git branch -t $i origin/$i; done
    git remote rm origin
    
  3. 이제 하위 프로젝트와 관련이없는 태그를 제거 할 수도 있습니다. 나중에 그렇게 할 수 있지만 다시 repo를 고치면 필요할 수 있습니다. 나는 그렇게하지 않았고 WARNING: Ref 'refs/tags/v0.1' is unchanged 모든 태그에 대해 (모두 하위 프로젝트와 관련이 없기 때문에); 또한 이러한 태그를 제거한 후 더 많은 공간이 재생됩니다. 보기에 git filter-branch 다른 태그를 다시 쓸 수 있어야하지만이를 확인할 수 없었습니다. 모든 태그를 제거하려면 사용하십시오 git tag -l | xargs git tag -d.

  4. 그런 다음 필터 브랜치를 사용하고 재설정하여 다른 파일을 제외하여 가지 치기 할 수 있습니다. 추가합시다 --tag-name-filter cat --prune-empty 빈 커밋을 제거하고 태그를 다시 작성하려면 (서명을 제거해야합니다) :

    git filter-branch --tag-name-filter cat --prune-empty --subdirectory-filter ABC -- --all
    

    또는 또는 헤드 브랜치를 다시 작성하고 태그 및 기타 분기를 무시하려면 다음과 같습니다.

    git filter-branch --tag-name-filter cat --prune-empty --subdirectory-filter ABC HEAD
    
  5. 그런 다음 백업 반사록을 삭제하여 공간을 진정으로 되 찾을 수 있습니다 (이제 작업이 파괴적이지만)

    git reset --hard
    git for-each-ref --format="%(refname)" refs/original/ | xargs -n 1 git update-ref -d
    git reflog expire --expire=now --all
    git gc --aggressive --prune=now
    

    그리고 이제 당신은 모든 역사가 보존 된 ABC 서브 디렉토리의 로컬 git 저장소를 가지고 있습니다.

참고 : 대부분의 용도로 git filter-branch 실제로 추가 된 매개 변수가 있어야합니다 -- --all. 네, 정말입니다 --우주-- all. 이것은 명령의 마지막 매개 변수 여야합니다. Matli가 발견 한 바와 같이, 이것은 프로젝트 분기와 태그를 새로운 리포지토리에 포함시킵니다.

편집 : 예를 들어, 저장소가 실제로 축소되었는지 확인하기 위해 아래 의견의 다양한 제안이 통합되었습니다 (이전의 경우는 아니 었습니다).

다른 팁

쉬운 방법™

이것은 매우 일반적이고 유용한 관행이므로 git의 관리자가 이를 정말 쉽게 만들었습니다. 하지만 최신 버전의 git(>= 2012년 5월 1.7.11)이 있어야 합니다.참조 부록 최신 git을 설치하는 방법에 대해 알아보세요.또한, 실제 사례 에서 연습 아래에.

  1. 이전 저장소 준비

    pushd <big-repo>
    git subtree split -P <name-of-folder> -b <name-of-new-branch>
    popd
    

    메모: <name-of-folder> 선행 또는 후행 문자를 포함하면 안 됩니다.예를 들어, subproject 다음과 같이 전달되어야 합니다. subproject, 아니다 ./subproject/

    Windows 사용자를 위한 참고 사항: 폴더 깊이가 1보다 큰 경우 <name-of-folder> *nix 스타일 폴더 구분 기호(/)가 있어야 합니다.예를 들어, path1\path2\subproject 다음과 같이 전달되어야 합니다. path1/path2/subproject

  2. 새 저장소 만들기

    mkdir <new-repo>
    pushd <new-repo>
    
    git init
    git pull </path/to/big-repo> <name-of-new-branch>
    
  3. 새 저장소를 Github 또는 다른 곳에 연결하세요.

    git remote add origin <git@github.com:my-user/new-repo.git>
    git push origin -u master
    
  4. 대청소, 만약 원한다면

    popd # get out of <new-repo>
    pushd <big-repo>
    
    git rm -rf <name-of-folder>
    

    메모:이렇게 하면 저장소에 모든 기록 참조가 남게 됩니다. 부록 실제로 비밀번호를 입력하는 것이 걱정되거나 파일 크기를 줄여야 하는 경우 아래를 참조하세요. .git 폴더.

...

연습

이들은 위와 동일한 단계, 그러나 다음을 사용하는 대신 내 저장소에 대한 정확한 단계를 따르십시오. <meta-named-things>.

다음은 노드에 JavaScript 브라우저 모듈을 구현하기 위한 프로젝트입니다.

tree ~/Code/node-browser-compat

node-browser-compat
├── ArrayBuffer
├── Audio
├── Blob
├── FormData
├── atob
├── btoa
├── location
└── navigator

하나의 폴더를 분할하고 싶은데, btoa, 별도의 git 저장소로

pushd ~/Code/node-browser-compat/
git subtree split -P btoa -b btoa-only
popd

이제 새로운 지점이 생겼습니다. btoa-only, 다음에 대한 커밋만 있습니다. btoa 새 저장소를 만들고 싶습니다.

mkdir ~/Code/btoa/
pushd ~/Code/btoa/
git init
git pull ~/Code/node-browser-compat btoa-only

다음으로 Github이나 bitbucket 등에서 새 저장소를 만들고 추가합니다. origin (그런데 "origin"은 명령의 일부가 아닌 관례일 뿐입니다. "remote-server" 또는 원하는 대로 부를 수 있습니다.)

git remote add origin git@github.com:node-browser-compat/btoa.git
git push origin -u master

행복한 날!

메모: 다음을 사용하여 저장소를 생성한 경우 README.md, .gitignore 그리고 LICENSE, 먼저 당겨야 합니다.

git pull origin -u master
git push origin -u master

마지막으로 더 큰 저장소에서 폴더를 제거하고 싶습니다.

git rm -rf btoa

...

부록

OS X의 최신 Git

최신 버전의 Git을 얻으려면:

brew install git

OS X용 Brew를 얻으려면:

http://brew.sh

우분투의 최신 자식

sudo apt-get update
sudo apt-get install git
git --version

그래도 작동하지 않으면(아주 오래된 우분투 버전을 사용하고 있는 경우) 시도해 보세요.

sudo add-apt-repository ppa:git-core/ppa
sudo apt-get update
sudo apt-get install git

그래도 문제가 해결되지 않으면 시도해 보세요.

sudo chmod +x /usr/share/doc/git/contrib/subtree/git-subtree.sh
sudo ln -s \
/usr/share/doc/git/contrib/subtree/git-subtree.sh \
/usr/lib/git-core/git-subtree

의견의 rui.araujo에게 감사드립니다.

기록 지우기

기본적으로 git에서 파일을 제거해도 실제로 git에서 해당 파일이 제거되는 것은 아니며, 해당 파일이 더 이상 존재하지 않는다는 점만 커밋됩니다.역사적 참조를 실제로 제거하려는 경우(예:비밀번호를 커밋한 경우) 다음을 수행해야 합니다.

git filter-branch --prune-empty --tree-filter 'rm -rf <name-of-folder>' HEAD

그 후에는 파일이나 폴더가 더 이상 git 기록에 전혀 표시되지 않는지 확인할 수 있습니다.

git log -- <name-of-folder> # should show nothing

그러나 당신은 삭제 내용을 github에 "푸시"할 수 없습니다 등등.시도하면 오류가 발생하므로 다음을 수행해야 합니다. git pull 당신이 할 수 있기 전에 git push -그리고 나서 당신은 당신의 역사에 있는 모든 것을 가지고 있는 상태로 돌아갑니다.

따라서 "원본"에서 기록을 삭제하려면(github, bitbucket 등에서 기록 삭제를 의미) 저장소를 삭제하고 저장소의 정리된 복사본을 다시 푸시해야 합니다.하지만 기다려 - 더있다!- 비밀번호 등을 없애는 것이 정말로 걱정된다면 백업을 정리해야 합니다(아래 참조).

만들기 .git 더 작은

앞서 언급한 기록 삭제 명령은 여전히 ​​많은 백업 파일 뒤에 남아 있습니다. 왜냐하면 git은 실수로 저장소를 망치지 않도록 도와주는 데 너무 친절하기 때문입니다.결국에는 며칠, 몇 달에 걸쳐 고아 파일이 삭제되지만 원하지 않는 항목을 실수로 삭제했다는 사실을 알게 될 경우를 대비해 잠시 동안 그대로 유지됩니다.

그러니 정말로 하고 싶다면 쓰레기통을 비워 에게 클론 크기 줄이기 저장소에서 즉시 다음과 같은 정말 이상한 작업을 모두 수행해야 합니다.

rm -rf .git/refs/original/ && \
git reflog expire --all && \
git gc --aggressive --prune=now

git reflog expire --all --expire-unreachable=0
git repack -A -d
git prune

그렇긴 하지만, 필요한 것을 알지 않는 한 이 단계를 수행하지 않는 것이 좋습니다. 잘못된 하위 디렉터리를 정리한 경우를 대비해서입니다.저장소를 푸시할 때 백업 파일은 복제되어서는 안 되며 로컬 복사본에만 있어야 합니다.

신용 거래

바울의 대답 새로운 저장소가 포함 된 /ABC를 생성하지만 /XYZ 내에서 /ABC를 제거하지는 않습니다. 다음 명령은 /xyz 내에서 /ABC를 제거합니다.

git filter-branch --tree-filter "rm -rf ABC" --prune-empty HEAD

물론, '클론-노이드 링크'저장소로 먼저 테스트 한 후 재설정, GC 및 Prune 명령 Paul 목록을 따라 따라갑니다.

새 저장소에서 오래된 역사를 올바르게 삭제하려면 다음에 조금 더 작업해야한다는 것을 알았습니다. filter-branch 단계.

  1. 클론과 필터를 수행하십시오.

    git clone --no-hardlinks foo bar; cd bar
    git filter-branch --subdirectory-filter subdir/you/want
    
  2. 오래된 역사에 대한 모든 참조를 제거하십시오. "Origin"은 클론을 추적하고 있었고 "원본"은 필터 브랜치가 이전 물건을 저장하는 곳입니다.

    git remote rm origin
    git update-ref -d refs/original/refs/heads/master
    git reflog expire --expire=now --all
    
  3. 지금도, 당신의 역사는 FSCK가 닿지 않는 팩 파일에 갇혀있을 수 있습니다. 파쇄에 찢어 새 팩 파일을 만들고 사용되지 않은 물체를 삭제하십시오.

    git repack -ad
    

거기 있습니다 이것에 대한 설명 에서 필터 브랜치 매뉴얼.

편집 : bash 스크립트가 추가되었습니다.

여기에 주어진 답변은 부분적으로 저를 위해 일했습니다. 많은 큰 파일이 캐시에 남아있었습니다. 마침내 일한 것 (Freenode의 #Git에서 몇 시간 후) :

git clone --no-hardlinks file:///SOURCE /tmp/blubb
cd blubb
git filter-branch --subdirectory-filter ./PATH_TO_EXTRACT  --prune-empty --tag-name-filter cat -- --all
git clone file:///tmp/blubb/ /tmp/blooh
cd /tmp/blooh
git reflog expire --expire=now --all
git repack -ad
git gc --prune=now

이전 솔루션으로 저장소 크기는 약 100MB였습니다. 이것은 그것을 1.7MB로 가져 왔습니다. 누군가를 도울 수도 있습니다 :)


다음 bash 스크립트는 작업을 자동화합니다.

!/bin/bash

if (( $# < 3 ))
then
    echo "Usage:   $0 </path/to/repo/> <directory/to/extract/> <newName>"
    echo
    echo "Example: $0 /Projects/42.git first/answer/ firstAnswer"
    exit 1
fi


clone=/tmp/${3}Clone
newN=/tmp/${3}

git clone --no-hardlinks file://$1 ${clone}
cd ${clone}

git filter-branch --subdirectory-filter $2  --prune-empty --tag-name-filter cat -- --all

git clone file://${clone} ${newN}
cd ${newN}

git reflog expire --expire=now --all
git repack -ad
git gc --prune=now

이것은 더 이상 복잡하지 않습니다. git 필터 브랜치 원하지 않는 하위 디렉토리를 컬링하기 위해 클론의 클론에 명령을 내린 다음 새 리모컨으로 밀어 넣으십시오.

git filter-branch --prune-empty --subdirectory-filter <YOUR_SUBDIR_TO_KEEP> master
git push <MY_NEW_REMOTE_URL> -f .

업데이트: git-subtree 모듈은 너무 유용하여 git 팀이 코어로 끌어 당겨서 만들었습니다. git subtree. 여기를 봐: 별도의 git 저장소로 디렉토리를 분리 (이동) 하위 디렉토리를 분리하십시오

git-subtree는 이것에 유용 할 수 있습니다

http://github.com/apenwarr/git-subtree/blob/master/git-subtree.txt (감가 상승)

http://psionides.jogger.pl/2010/02/04/sharing-code-between-projects-with-git-subtree/

다음은 작은 수정입니다 coolaj86'에스 "Easy Way ™"대답 분할하기 위해 다중 서브 폴더 (의 말을하자 sub1그리고 sub2) 새로운 git 저장소로.

Easy Way ™ (다중 서브 폴더)

  1. 오래된 repo를 준비하십시오

    pushd <big-repo>
    git filter-branch --tree-filter "mkdir <name-of-folder>; mv <sub1> <sub2> <name-of-folder>/" HEAD
    git subtree split -P <name-of-folder> -b <name-of-new-branch>
    popd
    

    메모: <name-of-folder> 선도적 또는 후행 캐릭터를 포함해서는 안됩니다. 예를 들어, 폴더가 명명되었습니다 subproject 통과해야합니다 subproject, 아니다 ./subproject/

    Windows 사용자의 참고 사항 : 폴더 깊이가> 1 인 경우 <name-of-folder> *nix 스타일 폴더 분리기 (/)가 있어야합니다. 예를 들어, 폴더가 명명되었습니다 path1\path2\subproject 통과해야합니다 path1/path2/subproject. 또한 사용하지 마십시오 mv명령하지만 move.

    최종 참고 : 기본 답변과의 독특하고 큰 차이는 스크립트의 두 번째 줄입니다. "git filter-branch..."

  2. 새 저장소를 만듭니다

    mkdir <new-repo>
    pushd <new-repo>
    
    git init
    git pull </path/to/big-repo> <name-of-new-branch>
    
  3. 새 저장소를 Github 또는 어디에 있든 연결하십시오

    git remote add origin <git@github.com:my-user/new-repo.git>
    git push origin -u master
    
  4. 대청소, 만약 원한다면

    popd # get out of <new-repo>
    pushd <big-repo>
    
    git rm -rf <name-of-folder>
    

    메모: 이것은 모든 역사적 참조를 저장소에 남겨 둡니다. 부록 원래 답변에서 실제로 비밀번호를 저 지르거나 파일 크기를 줄여야하는 경우 .git 폴더.

원래 질문은 XYZ/ABC/(*파일)이 ABC/ABC/(*파일)가되기를 원합니다. 내 자신의 코드에 대한 수락 된 답변을 구현 한 후 실제로 XYZ/ABC/(*파일)을 ABC/(*파일)로 변경하는 것을 알았습니다. 필터 브랜치 맨 페이지는 심지어 말합니다.

결과에는 해당 디렉토리가 포함됩니다. 프로젝트 루트로."

다시 말해, 최상위 폴더 "up"한 레벨을 홍보합니다. 예를 들어 내 역사상 최상위 폴더로 이름을 바꿨 기 때문에 중요한 차이점입니다. 폴더를 "Up"한 레벨을 홍보함으로써 GIT는 내가 이름을 변경 한 커밋에서 연속성을 잃습니다.

I lost contiuity after filter-branch

질문에 대한 나의 대답은 저장소의 2 부를 만들고 각각에 보관하려는 폴더를 수동으로 삭제하는 것입니다. Man Page는 이것으로 나를 뒷받침합니다.

...] 간단한 단일 커밋이 문제를 해결하기에 충분하다면 [이 명령] 사용하지 마십시오.

추가합니다 바울의 대답, 나는 궁극적으로 공간을 복구하기 위해서는 깨끗한 저장소로 헤드를 밀어야하고 .git/객체/팩 디렉토리의 크기를 낮추어야한다는 것을 알았습니다.

$ mkdir ...ABC.git
$ cd ...ABC.git
$ git init --bare

GC 자두 후에도 다음과 같습니다.

$ git push ...ABC.git HEAD

그런 다음 할 수 있습니다

$ git clone ...ABC.git

ABC/.git의 크기가 줄어 듭니다

실제로, 시간이 많이 걸리는 단계 (예 : Git GC)는 Repository를 청소하기위한 푸시로 필요하지 않습니다.

$ git clone --no-hardlinks /XYZ /ABC
$ git filter-branch --subdirectory-filter ABC HEAD
$ git reset --hard
$ git push ...ABC.git HEAD

지금 올바른 방법은 다음과 같습니다.

git filter-branch --prune-empty --subdirectory-filter FOLDER_NAME [first_branch] [another_branch]

Github는 이제 가지고 있습니다 작은 기사 그러한 경우에 대해.

그러나 원래 repo를 먼저 분리하여 디렉토리를 분리하여 (모든 파일 및 기타 디렉토리를 삭제할 수 있으므로) 연결해야 할 가능성이 높습니다.

따라서 알고리즘은 다음과 같습니다.

  1. 원격 저장소를 다른 디렉토리로 복제하십시오
  2. 사용 git filter-branch 일부 하위 디렉토리 아래에 파일 만 남겨두고 새 리모컨으로 푸시
  3. 원래 원격 저장소 에서이 하위 디렉토리를 제거하겠다는 커밋

여기서 답의 대부분 (모두?)이 어떤 형태에 의존하는 것으로 보입니다. git filter-branch --subdirectory-filter 그리고 그 ilk. 이것은 "대부분의 경우"가 작동하지만 경우에 따라 폴더로 이름을 바꾸는 경우 (예 : 예 :

 ABC/
    /move_this_dir # did some work here, then renamed it to

ABC/
    /move_this_dir_renamed

"move_me_renamed"를 추출하기 위해 일반적인 git 필터 스타일을 수행하면 처음에 Move_this_dir (처음으로 발생했을 때 발생한 파일 변경 기록을 잃게됩니다).심판).

따라서 실제로 유지하는 유일한 방법은 모두 변경 기록 (이와 같은 경우)은 본질적으로 저장소를 복사하고 (새 저장소를 만들고, 원산지로 설정 한 다음 다른 모든 것을 뉘우고 다음과 같이 하위 디렉토리를 부모에게 바꾸는 것입니다.

  1. 멀티 모듈 프로젝트를 현지에서 복제하십시오
  2. 분기 - 거기에 무엇이 있는지 확인하십시오. git branch -a
  3. 워크 스테이션에서 로컬 사본을 얻기 위해 분할에 포함될 각 지점에 결제를 수행하십시오. git checkout --track origin/branchABC
  4. 새 디렉토리로 사본을 만드십시오. cp -r oldmultimod simple
  5. 새 프로젝트 사본으로 이동 : cd simple
  6. 이 프로젝트에서 필요하지 않은 다른 모듈을 제거하십시오.
  7. git rm otherModule1 other2 other3
  8. 이제 대상 모듈의 서브 디르 만 남아 있습니다
  9. 모듈 루트가 새로운 프로젝트 루트가되도록 모듈 하위 디어를 제거하십시오.
  10. git mv moduleSubdir1/* .
  11. Relic Subdir 삭제 : rmdir moduleSubdir1
  12. 언제든지 변경 사항을 확인하십시오. git status
  13. 새로운 git repo를 만들고 URL을 복사 하여이 프로젝트를 지적하십시오.
  14. git remote set-url origin http://mygithost:8080/git/our-splitted-module-repo
  15. 이것이 좋습니다. git remote -v
  16. 변경 사항을 원격 저장소까지 푸시하십시오. git push
  17. 리모컨으로 가서 모든 것이 있는지 확인하십시오.
  18. 필요한 다른 지점에 대해 반복하십시오. git checkout branch2

이것은 다음과 같습니다 Github Doc "Subfolder를 새 저장소로 나누는 것" 6-11 단계 모듈을 새로운 리포지트로 푸시합니다.

이렇게하면 .git 폴더의 공간을 절약 할 수는 없지만 RENAME에서도 해당 파일의 모든 변경 기록을 유지합니다. 그리고 "많은"역사를 잃어버린 것 등이 없다면 이것은 그만한 가치가 없을 수도 있습니다. 그러나 적어도 당신은 나이가 많은 커밋을 잃지 않도록 보장됩니다!

나는이 문제가 정확히 있었지만 GIT 필터 브랜치를 기반으로 한 모든 표준 솔루션은 매우 느 렸습니다. 작은 저장소가 있다면 이것은 문제가되지 않을 수 있습니다. LibGit2를 기반으로 한 다른 GIT 필터링 프로그램을 작성하여 첫 번째 단계로서 1 차 리포지토리의 각 필터링에 대한 분기를 생성 한 다음 이들을 다음 단계로 푸시하십시오. 내 저장소 (500MB 100000 커밋)에서 표준 GIT 필터 브랜치 방법에는 며칠이 걸렸습니다. 내 프로그램은 동일한 필터링을 수행하는 데 몇 분이 걸립니다.

그것은 git_filter의 멋진 이름을 가지고 있으며 여기에 살고 있습니다.

https://github.com/slobobaby/git_filter

Github에서.

누군가에게 유용하기를 바랍니다.

그만한 가치가 있는 경우 Windows 시스템에서 GitHub를 사용하는 방법은 다음과 같습니다.다음 위치에 복제된 저장소가 있다고 가정해 보겠습니다. C:\dir1.디렉토리 구조는 다음과 같습니다. C:\dir1\dir2\dir3.그만큼 dir3 디렉토리는 제가 새로운 별도의 저장소로 만들고 싶은 디렉토리입니다.

Github:

  1. 새 저장소를 만듭니다. MyTeam/mynewrepo

배쉬 프롬프트:

  1. $ cd c:/Dir1
  2. $ git filter-branch --prune-empty --subdirectory-filter dir2/dir3 HEAD
    반환됨: Ref 'refs/heads/master' was rewritten (참고:dir2/dir3은 대소문자를 구분합니다.)

  3. $ git remote add some_name git@github.com:MyTeam/mynewrepo.git
    git remote add origin etc.작동하지 않아 반환됨 "remote origin already exists"

  4. $ git push --progress some_name master

나처럼 위에 언급했듯이, 나는 리버스 솔루션을 사용해야했다 (모든 커밋 삭제는 내 닿지 않는다 dir/subdir/targetdir)는 커밋의 약 95% (원하는대로)를 잘 제거하는 것처럼 보였습니다. 그러나 두 가지 작은 문제가 남아 있습니다.

첫 번째, filter-branch 코드를 소개하거나 수정하는 커밋을 제거하는 일을했지만 분명히 병합 커밋 Gitiverse의 역 아래에 있습니다.

이것은 내가 아마 살 수있는 미용 문제입니다. (그는 말한다 ... 눈을 피하고 천천히 물러서 다).

남아있는 소수의 커밋은 거의 없습니다 모두 복제! 나는 프로젝트의 전체 역사에 관한 두 번째 중복 타임 라인을 인수 한 것 같습니다. 흥미로운 점 (아래 그림에서 볼 수있는)은 내 3 개의 현지 지점이 모두 같은 타임 라인에 있지 않다는 것입니다 (이것은 확실히 그것이 존재하고 단지 수집 된 쓰레기가 아닙니다).

내가 상상할 수있는 유일한 것은 삭제 된 커밋 중 하나가 아마도 단일 합병이 filter-branch 실제로 삭제했습니다, 그리고 그것은 현재 무너진 각 스트랜드가 자체 커밋 사본을 가져 왔을 때 병렬 타임 라인을 만들었습니다. (어깨를 으쓱하다 내 타디는 어딨어?)이 문제를 해결할 수 있다고 확신합니다. 진짜 그것이 어떻게 일어 났는지 이해하는 것을 좋아합니다.

Crazy Mergefest-O-Rama의 경우, 나는 내 커밋 역사에서 너무나 확고하게 자리 잡았 기 때문에 그 사람을 내버려 둘 것입니다. 비 침습적 문제와 Tower.App에서는 꽤 예쁘기 때문입니다.

이 필터 명령을 사용하여 태그와 분기를 보존하는 동안 하위 디렉토리를 제거하십시오.

git filter-branch --index-filter \
"git rm -r -f --cached --ignore-unmatch DIR" --prune-empty \
--tag-name-filter cat -- --all

더 쉬운 방법

  1. 설치 git splits. 나는 그것을 기준으로 git 확장으로 만들었습니다. Jkeating의 솔루션.
  2. 디렉토리를 지역 지점으로 나눕니다 #change into your repo's directory cd /path/to/repo #checkout the branch git checkout XYZ
    #split multiple directories into new branch XYZ git splits -b XYZ XY1 XY2

  3. 어딘가에 빈 repo를 만듭니다. 우리는 우리가 빈 repo를 만들었다고 가정 할 것입니다 xyz 경로가있는 github에서 : git@github.com:simpliwp/xyz.git

  4. 새로운 repo로 밀어 넣으십시오. #add a new remote origin for the empty repo so we can push to the empty repo on GitHub git remote add origin_xyz git@github.com:simpliwp/xyz.git #push the branch to the empty repo's master branch git push origin_xyz XYZ:master

  5. 새로 생성 된 원격 저장소를 새로운 로컬 디렉토리로 클론
    #change current directory out of the old repo cd /path/to/where/you/want/the/new/local/repo #clone the remote repo you just pushed to git clone git@github.com:simpliwp/xyz.git

추천합니다 서브 폴더를 새로운 저장소로 분할하기위한 Github의 안내서. 단계는 비슷합니다 바울의 대답, 그러나 나는 그들의 지시를 이해하기 쉽다는 것을 알았습니다.

GitHub에서 호스팅 된 지역 저장소가 아닌 로컬 저장소를 신청하도록 지침을 수정했습니다.


하위 폴더를 새 저장소로 분할

  1. git bash를 엽니 다.

  2. 현재 작업 디렉토리를 새 저장소를 작성하려는 위치로 변경하십시오.

  3. 하위 폴더가 포함 된 저장소를 복제하십시오.

git clone OLD-REPOSITORY-FOLDER NEW-REPOSITORY-FOLDER
  1. 현재 작업 디렉토리를 복제 된 저장소로 변경하십시오.

cd REPOSITORY-NAME
  1. 저장소의 나머지 파일에서 하위 폴더를 필터링하려면 git filter-branch,이 정보 제공 :
    • FOLDER-NAME: 프로젝트 내의 폴더는 별도의 저장소를 만들고자합니다.
      • 팁 : Windows 사용자는 사용해야합니다 / 폴더를 구분합니다.
    • BRANCH-NAME: 예를 들어 현재 프로젝트의 기본 지점입니다. master 또는 gh-pages.

git filter-branch --prune-empty --subdirectory-filter FOLDER-NAME  BRANCH-NAME 
# Filter the specified branch in your directory and remove empty commits
Rewrite 48dc599c80e20527ed902928085e7861e6b3cbe6 (89/89)
Ref 'refs/heads/BRANCH-NAME' was rewritten

가비지 컬렉션 전에 "git reflog expire (expire = now)"와 같은 것이 필요할 수 있습니다. GIT 필터 브랜치는 히스토리에서 참조를 제거하지만 데이터를 보유하는 리플 로그 항목을 제거하지는 않습니다. 물론, 이것을 먼저 테스트하십시오.

초기 조건은 다소 다르지만 디스크 사용량이 극적으로 떨어졌습니다. 아마도-서브 디렉토리 필터는 이러한 요구를 무효화하지만 의심합니다.

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.

이것을 GitConfig에 넣으십시오.

reduce-to-subfolder = !sh -c 'git filter-branch --tag-name-filter cat --prune-empty --subdirectory-filter cookbooks/unicorn HEAD && git reset --hard && git for-each-ref refs/original/ | cut -f 2 | xargs -n 1 git update-ref -d && git reflog expire --expire=now --all && git gc --aggressive --prune=now && git remote rm origin'

나는 git subtree가 모두 훌륭하고 훌륭하다고 확신하지만, 내가 움직이고 싶은 Git Managed Code의 내 하위 디렉토리는 모두 일식에 있었다. 따라서 EGIT를 사용하는 경우 고통스럽게 쉽습니다. 이동하려는 프로젝트를 수행하고 팀-> 연결을 끊은 다음 팀-> 새로운 위치에 공유하십시오. 기존 Repo 위치를 사용하려고 시도하는 것은 기본값이지만 기존 선택을 선택 취소하고 새로운 장소를 선택하여 이동할 수 있습니다. 모든 우박을 자극합니다.

나는 매우 간단한 솔루션을 찾았습니다. 아이디어는 저장소를 복사 한 다음 불필요한 부분을 제거하는 것입니다. 이것이 작동하는 방식입니다.

1) 분할하려는 저장소를 복제하십시오

git clone git@git.thehost.io:testrepo/test.git

2) git 폴더로 이동하십시오

cd test/

2) 불필요한 폴더를 제거하고 커밋하십시오

rm -r ABC/
git add .
enter code here
git commit -m 'Remove ABC'

3) 불필요한 폴더를 제거하여 BFG

cd ..
java -jar bfg.jar --delete-folders "{ABC}" test
cd test/
git reflog expire --expire=now --all && git gc --prune=now --aggressive

곱하기 폴더의 경우 쉼표를 사용할 수 있습니다

java -jar bfg.jar --delete-folders "{ABC1,ABC2}" metric.git

4) 히스토리가 방금 삭제 한 파일/폴더가 포함되어 있지 않은지 확인하십시오.

git log --diff-filter=D --summary | grep delete

5) 이제 ABC가없는 깨끗한 저장소가 있으므로 새로운 원산지로 밀어 넣으십시오.

remote add origin git@github.com:username/new_repo
git push -u origin master

그게 다야. 다른 저장소를 얻기 위해 단계를 반복 할 수 있습니다.

XY1, XY2를 제거하고 3 단계에서 XYZ-> ABC 이름 바꾸기 만하면됩니다.

당신은 쉽게 시도 할 수 있습니다 https://help.github.com/enterprise/2.15/user/articles/splitting-a-subfolder-ounto-a-new-repository/

이것은 나를 위해 효과가있었습니다. 위에서 주어진 단계에서 직면 한 문제는

  1. 이 명령에서 git filter-branch --prune-empty --subdirectory-filter FOLDER-NAME BRANCH-NAME 그만큼 BRANCH-NAME ~이다 주인

  2. 보호 문제로 인해 커밋 할 때 마지막 단계가 실패하면 https://docs.gitlab.com/ee/user/project/protected_branches.html

라이센스 : CC-BY-SA ~와 함께 속성
제휴하지 않습니다 StackOverflow
scroll top