Programming

자식 하위 디렉토리를 추출하고 하위 모듈을 만드는 방법은 무엇입니까?

procodes 2020. 7. 27. 08:06
반응형

자식 하위 디렉토리를 추출하고 하위 모듈을 만드는 방법은 무엇입니까?


몇 달 전에 프로젝트를 시작하고 모든 것을 기본 디렉토리에 저장했습니다. 내 기본 디렉토리 "Project"에는 다른 것들을 포함하는 여러 하위 디렉토리가 있습니다. Project / paper에는 LaTeX로 작성된 문서가 들어 있습니다. Project / sourcecode / RailsApp에는 rails 앱이 있습니다.

"Project"는 GITified이며 "paper"와 "RailsApp"디렉토리에 많은 커밋이있었습니다. 이제 "RailsApp"에 cruisecontrol.rb를 사용하고 싶습니다. 역사를 잃지 않고 "RailsApp"에서 하위 모듈을 만드는 방법이 있는지 궁금합니다.


요즘에는 수동으로 git filter-branch를 사용하는 것보다 훨씬 쉬운 방법이 있습니다 .git subtree

설치

참고 git-subtree 는 이제 git1.7.11 기준 (contrib를 설치 한 경우)의 일부이므로 이미 설치했을 수 있습니다. 를 실행하여 확인할 수 있습니다 git subtree.


소스에서 git-subtree를 설치하려면 (이전 버전의 git) :

git clone https://github.com/apenwarr/git-subtree.git

cd git-subtree
sudo rsync -a ./git-subtree.sh /usr/local/bin/git-subtree

또는 매뉴얼 페이지를 원한다면

make doc
make install

용법

큰 조각을 작은 조각으로 나눕니다.

# Go into the project root
cd ~/my-project

# Create a branch which only contains commits for the children of 'foo'
git subtree split --prefix=foo --branch=foo-only

# Remove 'foo' from the project
git rm -rf ./foo

# Create a git repo for 'foo' (assuming we already created it on github)
mkdir foo
pushd foo
git init
git remote add origin git@github.com:my-user/new-project.git
git pull ../ foo-only
git push origin -u master
popd

# Add 'foo' as a git submodule to `my-project`
git submodule add git@github.com:my-user/new-project.git foo

자세한 설명서 (맨 페이지)를 읽으십시오 git-subtree.txt.


체크 아웃 git filter-branch .

매뉴얼 페이지 Examples섹션 은 하위 디렉토리를 자체 프로젝트로 추출하는 방법을 보여 주면서 모든 히스토리를 유지하고 다른 파일 / 디렉토리의 히스토리를 삭제합니다 (원하는 것).

foodir/프로젝트 루트 인 것처럼 보이도록 저장소를 다시 작성하고 다른 모든 히스토리를 삭제 하려면 다음을 수행하십시오 .

   git filter-branch --subdirectory-filter foodir -- --all

따라서 라이브러리 서브 디렉토리를 자체의 저장소로 전환 할 수 있습니다.
노트 --이 분리형의 filter-branch개정 옵션에서 옵션을, 그리고이 --all모든 브랜치와 태그를 재 작성 할 수 있습니다.


이를 수행하는 한 가지 방법은 반대입니다. 유지하려는 파일을 제외한 모든 것을 제거하십시오.

기본적으로 리포지토리 의 복사본 을 만든 다음 git filter-branch보관하려는 파일 / 폴더를 제외한 모든 것을 제거 하는 사용 하십시오.

예를 들어, 파일 tvnamer.py을 새 저장소 로 추출하려는 프로젝트가 있습니다 .

git filter-branch --tree-filter 'for f in *; do if [ $f != "tvnamer.py" ]; then rm -rf $f; fi; done' HEAD

이를 git filter-branch --tree-filter통해 각 커밋을 진행하고 명령을 실행하고 결과 디렉토리 내용을 다시 커밋합니다. 이것은 매우 파괴적이므로 (저장소 사본에서만이 작업을 수행해야합니다!) 시간이 걸릴 수 있습니다 (300 개의 커밋과 약 20 개의 파일이있는 저장소에서 약 1 분)

위의 명령은 각 개정판에서 다음 셸 스크립트를 실행합니다. 물론 수정해야합니다 (하위 디렉토리 대신 제외 tvnamer.py).

for f in *; do
    if [ $f != "tvnamer.py" ]; then
        rm -rf $f;
    fi;
done

가장 큰 명백한 문제는 모든 커밋 메시지가 나머지 파일과 관련이없는 경우에도 모든 커밋 메시지를 남긴다는 것입니다. 스크립트 git-remove-empty-commits 는 이것을 수정합니다.

git filter-branch --commit-filter 'if [ z$1 = z`git rev-parse $3^{tree}` ]; then skip_commit "$@"; else git commit-tree "$@"; fi'

당신 (기본적으로 백업)에 무엇이든 -fforce 인수를 filter-branch다시 사용해야합니다.refs/original/

Of course this will never be perfect, for example if your commit messages mention other files, but it's about as close a git current allows (as far as I'm aware anyway).

Again, only ever run this on a copy of your repository! - but in summary, to remove all files but "thisismyfilename.txt":

git filter-branch --tree-filter 'for f in *; do if [ $f != "thisismyfilename.txt" ]; then rm -rf $f; fi; done' HEAD
git filter-branch -f --commit-filter 'if [ z$1 = z`git rev-parse $3^{tree}` ]; then skip_commit "$@"; else git commit-tree "$@"; fi'

Both CoolAJ86 and apenwarr answers are very similar. I went back and forth between the two trying to understand bits that were missing from either one. Below is a combination of them.

First navigate Git Bash to the root of the git repo to be split. In my example here that is ~/Documents/OriginalRepo (master)

# move the folder at prefix to a new branch
git subtree split --prefix=SubFolderName/FolderToBeNewRepo --branch=to-be-new-repo

# create a new repository out of the newly made branch
mkdir ~/Documents/NewRepo
pushd ~/Documents/NewRepo
git init
git pull ~/Documents/OriginalRepo to-be-new-repo

# upload the new repository to a place that should be referenced for submodules
git remote add origin git@github.com:myUsername/newRepo.git
git push -u origin master
popd

# replace the folder with a submodule
git rm -rf ./SubFolderName/FolderToBeNewRepo
git submodule add git@github.com:myUsername/newRepo.git SubFolderName/FolderToBeNewRepo
git branch --delete --force to-be-new-repo

Below is a copy of above with the customize-able names replaced and using https instead. Root folder is now ~/Documents/_Shawn/UnityProjects/SoProject (master)

# move the folder at prefix to a new branch
git subtree split --prefix=Assets/SoArchitecture --branch=so-package

# create a new repository out of the newly made branch
mkdir ~/Documents/_Shawn/UnityProjects/SoArchitecture
pushd ~/Documents/_Shawn/UnityProjects/SoArchitecture
git init
git pull ~/Documents/_Shawn/UnityProjects/SoProject so-package

# upload the new repository to a place that should be referenced for submodules
git remote add origin https://github.com/Feddas/SoArchitecture.git
git push -u origin master
popd

# replace the folder with a submodule
git rm -rf ./Assets/SoArchitecture
git submodule add https://github.com/Feddas/SoArchitecture.git
git branch --delete --force so-package

If you want to transfer some subset of files to a new repository but keep the history, you're basically going to end up with a completely new history. The way this would work is basically as follows:

  1. Create new repository.
  2. For each revision of your old repository, merge the changes to your module into the new repository. This will create a "copy" of your existing project history.

It should be somewhat straightforward to automate this if you don't mind writing a small but hairy script. Straightforward, yes, but also painful. People have done history rewriting in Git in the past, you can do a search for that.

Alternatively: clone the repository, and delete the paper in the clone, delete the app in the original. This would take one minute, it's guaranteed to work, and you can get back to more important things than trying to purify your git history. And don't worry about the hard drive space taken up by redundant copies of history.

참고URL : https://stackoverflow.com/questions/920165/how-to-extract-a-git-subdirectory-and-make-a-submodule-out-of-it

반응형