JS

2013년 8월 7일 수요일

Git subtree를 이용한 작업

다음과 같은 상황을 생각해보자. 현재 프로젝트 디렉토리 구조는 다음과 같다.
myproject/
        .git/
        app1/
                app1-files
        app2/
        others
그런데 여기서 app1만 떼어내서 프로젝트를 새로 만들고 싶다. 그리고 git 히스토리는 최대한 유지하고 싶다.
project-app1/
        .git/
        app1/
                app1-files

스택오버플로우에서 비슷한 질문을 찾았다.
http://stackoverflow.com/questions/359424/detach-subdirectory-into-separate-git-repository

처음에는 추천수를 가장 많이 받은 방법을 따라해보았다. (내가 실수해서 그렇게 되었을 가능성도 있지만) 저 방법을 그대로 따라하니 다음과 같이 되었다.
project-app1/
        .git/
        app1-files
그래서 디렉토리 구조를 또 바꿔야 하는데 이것도 filter-branch를 잘 쓰면 가능하겠지만 방법을 찾기 어려웠다. 어떻게 하다보니 찾게된 방법이 subtree를 이용하고 있었다.
http://stackoverflow.com/questions/1425892/how-do-you-merge-two-git-repositories

그래서 그냥 처음부터 subtree만 써서 다시 작업을 하면 좋겠다는 생각이 들었다. 최신 버전의 git을 설치하는 것도 문제인데 여기엔 적지 않겠다. (경우에 따라 소스를 직접 받아서 컴파일해야 할 수도 있다.)

디렉토리 분리

먼저 app1 디렉토리를 분리하는 여기를 참고해서 다음과 같이 하면 된다.
cd ~/path/myproject
git subtree split -P app1 -b app1-only
cd ~/path
여기서 -P 다음엔 디렉토리 이름을 적고, -b 다음에는 branch 이름을 적당히 적으면 된다.
mkdir ~/path/app1
cd ~/path/app1
git init
git pull ~/path/myproject app1-only
이렇게 하면 ~/path/app1 디렉토리에 app1의 내용만 분리된다. 원래의 myprojcet 디렉토리에서 app1을 삭제하는 방법은 참고한 글에 나온다. 그리고 참고한 글에 적힌 remote add는 생략한다.

디렉토리 가져오기

이제 디렉토리를 새로 만들어서 app1을 집어 넣어야 한다. 이것은 여기를 참고하였다. 다만 git subtree add를 하기 전에 뭔가 commit을 해두어야만 하는 것 같다.
mkdir ~/path/project-app1
cd ~/path/project-app1
git init
git add something
git commit something
git subtree add --prefix app1 ~/path/app1 master
이렇게 하면 처음에 원했던 작업이 완료된다. 다만 app1/somefile을 수정한 후 subtree add 이전의 커밋과 비교하는 것은 불가능하다. 처음 디렉토리에 대한 상대 경로가 변경되어서 그런 것 같다.

전체 히스토리에서 파일 삭제

생각을 더 해봤는데 더 좋은 방법이 있는 것 같다. 일단 myproject를 통채로 복사하고 디렉토리 이름을 project-app1으로 바꾼다. 이 디렉토리는 .git의 상위 디렉토리이므로 이름을 마음대로 바꿀 수 있다. 그리고 project-app1 디렉토리 내에서 불필요한 파일과 그에 해당하는 히스토리를 통채로 삭제해 버리면 된다. 이렇게 하는 방법은 다음 글에 적혀 있다.

댓글 1개:

  1. subdir을 분리하면서 history외에 branch와 tag를 살리는 방법은 없을까요?

    답글삭제