아래의 내용은 정리하면서 검증한 부분도 있지만, 검증이 되지 않고 정리된 내용도 있을 수 있으므로, 반드시 관련된 정보를 추가로 검색하여 검증해야 한다.
Submodule?
Git 프로젝트는 하나의 독립된 라이브러리라고 생각할 수 있다. 따라서 특정 프로젝트를 진행할 때 또 다른 프로젝트를 내부적으로 사용해야하는 경우가 빈번하게 발생할 수 있다. 일반적으로 이런 상황에서는 필요한 라이브러리의 특정 버전을 설치하거나 소스를 복사해서 사용하는 방법을 사용하는데 이에 따른 버전관리나 소스의 변경등에 대한 대처가 만만치 않다.
Git와 Submodule을 사용하면 Git Repository 내에 또 다른 독립적인 Repository를 운영하는 구조를 만들 수 있다. 당연히 각 Repository는 독립적으로 관리된다.
이런 상황이 새로운 것일까?
Node 환경이라면 이미 npm을 이용해서 package를 관리하며 사용하고 있다. 그런데 가져다 쓸 패키지가 git에 repository로만 존재하는 경우라면 어떻게 해야할 까?
이런 상황에 대체하기 위한 것이 submodule이고 정리하면
“submodule은 git repository 하위에 다른 git repository를 관리하기 위한 도구”
라고 생각하면 된다.
자세한 내용은 Pro Git의 내용을 참고!
사용법 정리
기본 옵션들
git submodule에 대한 공식 옵션은 다음의 명령으로 확인 가능하다.
main project와 submodule project 관계
main project에 submodule을 추가하면 submodule들을 관리하기 위한
.gitmodules
파일이 생성되고 여기에 submoudle에 대한 폴더와 repository 정보가 관리되며 main project는 추가된 submodule에 대한 commit point를 바라보고 있게 된다.
따라서 main project와 submodule 간의 처리는 아래와 같은 순서에 주의해야 한다.
clone / pull / update : 리모트에서 로컬로 데이터를 가져올 경우는
Parent 먼저
처리 후 submodule을 처리해야 한다.
commit / push : 로컬 commit과 리모트로 데이터를 전송하는 경우는
submodule 먼저
처리 후 Parent를 처리해야 한다.
main project가 submodule에 대한 commit point를 연계하고 있기 떄문에 위의 순서가 맞지 않으면 잘못된 submodule의 commit point를 바라보게 되므로 문제가 발생할 수 있다.
submodule 추가
정상적으로 추가되면 main project 경로에 .gitmodules 파일이 생성되며, 내용은 아래와 같이 구성된다.
위와 같이 Root Repository (여기서는 Hugo로 만든 사이트) 를 기준으로 경로와 git repository url이 관리되고 있는 것을 확인할 수 있다.
submodule이 추가된 것은 main project가 변경된 것을 의미하기 때문에 commit을 수행해 줘야 한다. 특정 branch로 지정할 경우는 -b <branch name>을 사용하면 된다. 또한 나중에 submodule에 대한 branch를 설정할 경우는 아래와 같이 처리할 수도 있다.
submodule 상태 확인
기본적인 git 상태 확인은 아래의 명령을 사용하며 submodule과 연동해서 사용할 수 있다.
main project에서 바라보는 submodule 상태
위의 내용을 검토해 보면 다음과 같은 특징이 존재한다.
mode 160000은 일반적인 파일이나 디렉토리가 아니라는 의미를 가진다.
Subproject commit 51dbdcf4aaef01d02e78a6ea76b2a6fde5842b55는 main project가 submodule repository의 51dbdcf4aaef01d02e78a6ea76b2a6fde5842b55 commit 정보를 바라보고 있다는 의미를 가진다.
Detached HEAD 문제
Detached HEAD 문제란 submodule update 명령이 수행되면 해당 submodule이 어떤 branch에도 속하지 않는 분리된 HEAD 정보를 가지는 상태를 말하는 것으로 branch를 지정해 줘야 한다. 따라서 아래와 같이 각 단계별 명령을 수행할 때 지정해 주는 것이 좋다.
git detached HEAD에 대한 내용은 정보를 참고하고, submodule과 detached HEAD에 대한 내용은 정보를 참고하면 된다.
단축 명령 및 Config 설정
위에서 알아본 명령들을 별칭(Alias) 등록을 통해서 단축 명령으로 수행할 수도 있다.
main project에 아래와 같이 정보를 설정해 두면 활용하기 쉽다.
이미 submodule을 포함하고 있는 Repository 활용하기
clone and update submodules
Parent git project clone : .gitmodules 파일이 존재하며, 파일내에 어떤 폴더에 어떤 git repository를 사용하는지에 대한 정보를 알 수 있다.
submodule clone
위의 clone 과정을 한번에 처리할 수도 있다.
$ git clone –recurse-submodules <main project repository>
$ git submodule foreach git checkout
이미 로컬에 submodule이 존재하는 경우 갱신
commit and push submodules
만일 새로운 branch로 작업하는 경우
변경된 코드들 commit
push submodules
commit and push main project
위에서 언급한 것과 같이 push를 할 때는 반드시
submodule들을 먼저 처리하고 main project를 처리
해야 한다. 따라서 submodule들이 모두 push되었는지를 확인해야 한다.
매번 명령어를 지정해서 처리하는 것을 항상 처리할 수 될 수 있도록 하기 위해서는 아래와 같이 설정으로 처리해 두면 된다.
submodule 제거
.gitmodules 파일에서 대상 submodule 정보를 삭제한다.
변경된 내용을 stage 처리 한다.
.git/config 파일에서 대상 submodule 정보를 삭제한다.
git 에서 cached 인덱스 정보를 제거한다.
./git/modules 폴더에서 대상 submodule 폴더 정보를 삭제한다.
변경된 내용을 commit 한다.
제거된 submodule 폴더를 삭제한다.
위의 내용은 기본적인 git 명령을 사용한 것이고 submodule 명령을 통하면 다음과 같이 더 간단하게 처리가 가능할 수 있다.