많은 하위 디렉터리를 별도의 새로운 Git 저장소로 분리
이 질문은 하위 디렉터리를 별도의 Git 저장소로 분리하는 것을 기반으로 합니다.
하나의 서브디렉토리를 분리하는 것이 아니라 몇 개를 분리하고 싶습니다.예를 들어, 현재 디렉터리 트리는 다음과 같습니다.
/apps
/AAA
/BBB
/CCC
/libs
/XXX
/YYY
/ZZZ
그 대신에 이것을 원합니다.
/apps
/AAA
/libs
/XXX
--subdirectory-filter
논쟁git filter-branch
처음 실행할 때 주어진 디렉토리를 제외한 모든 것을 제거하기 때문에 작동하지 않습니다.하는 줄 요.--index-filter
원하지 않는 모든 파일에 대한 인수는 지루하지만, 두 번 이상 실행을 시도하면 다음과 같은 메시지가 나타납니다.
Cannot create a new backup.
A previous backup already exists in refs/original/
Force overwriting the backup with -f
무슨 생각 있어요? TIA.
subshell을 처리하고 ext glob(skynan이 제안한 대로)을 사용하는 대신 다음과 같은 훨씬 간단한 접근 방식을 시도해 보십시오.
git filter-branch --index-filter 'git rm --cached -qr --ignore-unmatch -- . && git reset -q $GIT_COMMIT -- apps/AAA libs/XXX' --prune-empty -- --all
무효로 언급된 바와 같이.포인터의 코멘트, 이것은 다음을 제외한 모든 것을 제거할 것입니다.apps/AAA
그리고.libs/XXX
현재 저장소에서.
빈 병합 커밋 제거
이것은 많은 빈 병합을 남깁니다.이것들은 그의 답변에서 알파벳으로 설명된 다른 패스로 제거할 수 있습니다.
git filter-branch --prune-empty --parent-filter \
'sed "s/-p //g" | xargs -r git show-branch --independent | sed "s/\</-p /g"'
⚠️ 경고:위는 GNU 버전을 사용해야 합니다.sed
그리고.xargs
그렇지 않으면 다음과 같은 모든 커밋을 제거할 것입니다.xargs
패.brew install gnu-sed findutils
그 다음에 사용합니다.gsed
그리고.gxargs
:
git filter-branch --prune-empty --parent-filter \
'gsed "s/-p //g" | gxargs git show-branch --independent | gsed "s/\</-p /g"'
쉬운 해결책: git-filter-repo
비슷한 문제가 있었는데 여기 나열된 여러 가지 방법을 검토한 결과 git-filter-repo를 발견했습니다.여기 공식 git 문서에서 git-filter-branch의 대안으로 추천합니다.
기존 저장소의 디렉토리 부분 집합에서 새 리포지토리를 만들려면 다음 명령을 사용합니다.
git filter-repo --path <file_to_keep>
여러 파일/폴더를 체인 방식으로 필터링:
git filter-repo --path keepthisfile --path keepthisfolder/
따라서 git-filter-repo를 사용하여 원래 질문에 답하려면 다음 명령만 있으면 됩니다.
git filter-repo --path apps/AAA/ --path libs/XXX/
간단한 git 명령을 사용한 수동 단계
이 계획은 개별 디렉토리를 자체 저장소로 분할한 다음 이를 병합하는 것입니다.다음 수동 단계에서는 geek-to-use 스크립트를 사용하지 않고 이해하기 쉬운 명령을 사용하여 추가 N개의 하위 폴더를 다른 단일 저장소로 병합하는 데 도움이 될 수 있습니다.
나누다
원래 레포를 다음과 같이 가정합니다. original_repo
1 - 앱 분할:
git clone original_repo apps-repo
cd apps-repo
git filter-branch --prune-empty --subdirectory-filter apps master
2 - 갈라진 입술
git clone original_repo libs-repo
cd libs-repo
git filter-branch --prune-empty --subdirectory-filter libs master
폴더가 2개 이상 있으면 계속합니다.이제 두 개의 새로운 임시 깃 저장소를 갖게 됩니다.
앱과 립을 병합하여 정복하기
3 - 새 레포를 준비합니다.
mkdir my-desired-repo
cd my-desired-repo
git init
그리고 적어도 하나의 약속을 해야 할 것입니다.다음 세 줄을 건너뛰어야 할 경우 첫 번째 레포가 레포 루트 바로 아래에 나타납니다.
touch a_file_and_make_a_commit # see user's feedback
git add a_file_and_make_a_commit
git commit -am "at least one commit is needed for it to work"
merge
나중 섹션의 명령이 예상대로 중지됩니다.
합니다와 같은 .a_file_and_make_a_commit
, 당신은 a를 추가할 것을 선택할 수 있습니다..gitignore
, 아니면README.md
타
4 - 앱 레포를 먼저 병합합니다.
git remote add apps-repo ../apps-repo
git fetch apps-repo
git merge -s ours --no-commit apps-repo/master # see below note.
git read-tree --prefix=apps -u apps-repo/master
git commit -m "import apps"
이제 새 저장소 안에 apps 디렉토리가 표시됩니다.git log
모든 관련 기록 커밋 메시지를 표시해야 합니다.
와 같이의 경우 를 : Chris git 의(>2.9) 의.--allow-unrelated-histories
와 함께git merge
5 - 립스 레포를 다음과 같은 방법으로 병합합니다.
git remote add libs-repo ../libs-repo
git fetch libs-repo
git merge -s ours --no-commit libs-repo/master # see above note.
git read-tree --prefix=libs -u libs-repo/master
git commit -m "import libs"
병합할 리포지토리가 2개 이상 있으면 계속합니다.
참조:다른 리포지토리의 하위 디렉터리를 git와 병합합니다.
를 하려고 합니까?filter-branch
한 번 이상?할 수 다항)).extglob
사용할 수 있도록 셸에서 활성화):
git filter-branch --index-filter "git rm -r -f --cached --ignore-unmatch $(ls -xd apps/!(AAA) libs/!(XXX))" --prune-empty -- --all
이렇게 않는 하위 되고 합니다(, )로 을 미치지 않는 한 및 --prune-empty
- -
이 후 않는 는 됩니다에서 되지 않은 됩니다.git status
.
$(ls ...)
합니다.extglob
됩니다.됩니다sh
eval
()extglob
사용할 수 없음).git에서 셸 옵션을 활성화하려면 어떻게 해야 합니까?를 참조하십시오.그것에 대한 더 자세한 사항을 위하여.
여기서 제 질문에 답을 드리자면...우여곡절 끝에
는 를 할수.git subtree
및 . 이 지침은 다음을 기반으로 합니다.
- git 하위 트리로 프로젝트 간 코드 공유 – http://psionides.jogger.pl/2010/02/04/sharing-code-between-projects-with-git-subtree/
- 직무에 적합한 도구: git- stitch-repo – http://ifup.org/2009/02/07/the-right-tool-for-the-job-git-stitch-repo/
먼저 별도의 저장소에 보관할 디렉토리를 꺼냈습니다.
cd origRepo
git subtree split -P apps/AAA -b aaa
git subtree split -P libs/XXX -b xxx
cd ..
mkdir aaaRepo
cd aaaRepo
git init
git fetch ../origRepo aaa
git checkout -b master FETCH_HEAD
cd ..
mkdir xxxRepo
cd xxxRepo
git init
git fetch ../origRepo xxx
git checkout -b master FETCH_HEAD
그런 다음 빈 저장소를 새로 만들고 마지막 두 개를 가져오거나 연결했습니다.
cd ..
mkdir newRepo
cd newRepo
git init
git-stitch-repo ../aaaRepo:apps/AAA ../xxxRepo:libs/XXX | git fast-import
이렇게 하면 두 개의 가지가 생기고,master-A
그리고.master-B
, 연결된 저장소 중 하나의 내용을 각각 보유하고 있습니다.이들을 결합하고 정리하는 방법:
git checkout master-A
git pull . master-B
git checkout master
git branch -d master-A
git branch -d master-B
지금은 어떻게/언제 이런 일이 일어나는지 잘 모르겠지만, 첫번째 사건 이후로checkout
그리고.pull
, 코드는 마법처럼 마스터 브랜치에 합쳐집니다(여기서 무슨 일이 일어나고 있는지에 대한 어떤 통찰력이라도 감사히 받겠습니다!).
모든 것이 예상대로 작동한 것 같은데요, 다만 제가 자세히 들여다보면요.newRepo
이 commit history,다에 영향을 미쳤을 때 되는 것이 .apps/AAA
그리고.libs/XXX
할 수 있는 중복을 제거할 수 있는 방법이 있다면 완벽할 것 같습니다.
저는 이 문제를 정확히 해결하기 위해 깃 필터를 작성했습니다.git_filter라는 환상적인 이름을 가지고 있으며 여기 github에 위치해 있습니다.
https://github.com/slobobaby/git_filter
그것은 훌륭한 libgit2를 기반으로 합니다.
커밋이 많은 대용량 저장소를 분할해야 했는데(~100000개) git filter-branch 기반 솔루션을 실행하는 데 며칠이 걸렸습니다. git_filter는 동일한 작업을 수행하는 데 1분이 걸립니다.
git split' git 확장자 사용
git splits
bash 스크립트는 포장지 주변에 있는 bash script입니다.git branch-filter
Jkeating의 솔루션을 바탕으로 Git 확장으로 만든 것입니다.
이것은 정확히 이 상황을 위해 만들어졌습니다.git splits -f
백업을 강제로 제거하는 옵션입니다..git splits
새 분기에서 작동하므로 현재 분기를 다시 쓸 수 없으므로 백업은 관련이 없습니다.자세한 내용은 readme을 참조하고 repo의 복사본/클론에 사용하십시오(만일의 경우를 대비하여!).
- 설치.
합니다.
#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 apps/AAA libs/ZZZ어딘가에 빈 레포를 만듭니다.포(repo)입니다라는 빈를 만들었다고
xyz
진 GitHub에서:git@github.com:simpliwp/xyz.git
새 레포로 이동합니다.
#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
를 새
#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
git clone git@example.com:thing.git
cd thing
git fetch
for originBranch in `git branch -r | grep -v master`; do
branch=${originBranch:7:${#originBranch}}
git checkout $branch
done
git checkout master
git filter-branch --index-filter 'git rm --cached -qr --ignore-unmatch -- . && git reset -q $GIT_COMMIT -- dir1 dir2 .gitignore' --prune-empty -- --all
git remote set-url origin git@example.com:newthing.git
git push --all
을 덮어씁니다. .-f
o로 때filter-branch
그 경고를 무시할 수 있습니다. 있다고 합니다. ( 원하지 를 한 입니다. :) 그렇지 않으면 해결책이 있다고 생각합니다(즉, 원하지 않는 디렉토리를 한 번에 제거하는 것).filter-branch
).
다음 경로에 해당하는 커밋을 내보내는 것이 더 쉽다고 생각합니다.
git log --pretty=email --patch-with-stat --reverse --full-index --binary -- /apps/{AAA,BBB,CCC} /libs/{XXX,YYY,ZZZ} > subdir.patch
다음과 같은 커밋을 새 레포로 가져옵니다.
git am < subdir.patch
할 수 를 해 볼 수 .-m --first-parent
:
git log --pretty=email --patch-with-stat --reverse --full-index --binary -m --first-parent -- <your paths>
메시지가 제시하는 것처럼 refs/original의 .git 디렉토리 아래에 있는 백업을 삭제합니다.디렉터리가 숨겨져 있습니다.
언급URL : https://stackoverflow.com/questions/2982055/detach-many-subdirectories-into-a-new-separate-git-repository
'source' 카테고리의 다른 글
MySQL에 decimal을 저장하는 방법은? (0) | 2023.10.03 |
---|---|
UNIX 휴대용 원자 작동 (0) | 2023.09.28 |
PowerShell 오류 메시지에서 touch 명령으로 새 파일 만들기 (0) | 2023.09.28 |
jQuery UI 대화상자에서 첫번째 텍스트 상자에 포커스를 설정하지 못하도록 합니다. (0) | 2023.09.28 |
팬더를 코드에 적용하려면 언제 사용해야 합니까? (0) | 2023.09.28 |