일반

[GIT] Submodule (Nested Repository) 사용하기

Posted 2015. 05. 25 Updated 2020. 08. 28 Views 10908 Replies 0
?

단축키

Prev이전 문서

Next다음 문서

ESC닫기

크게 작게 위로 아래로 댓글로 가기 인쇄

GIT을 사용하여 버전관리를 하다 보면, GIT 저장소(Repository) 안에 또 다른 저장소를 만들어서 사용하고 싶은 경우가 있습니다. 규모가 어느 정도 되는 프로젝트에서 전체 프로그램을 기능별로 모듈화해서 작성하고 각각 따로 버전관리를 하고자 하는 경우가 이에 해당하는 상황일 것입니다. 모듈별로 따로 버전관리를 할 수 있다면, 재사용과 이식성 면에서도 크게 도움이 되기 때문이죠.

GIT에서는 이런 경우에 대비하여 서브모듈(Submodule)이라는 기능을 제공합니다. 서브모듈은 위와 같이 중첩된 Repository를 관리하기 위해 GIT에서 제공하는 기능입니다.

설명의 편의상 전체 프로젝트를 관리하는 저장소를 Master Repository라 하고, 여기에 속해 있는 서브모듈을 Slave Repository라 하도록 하겠습니다.


서브모듈 추가하기

서브모듈은 .gitmodules라는 이름의 파일로 관리됩니다. 중첩된 저장소를 관리하는 파일이니까 뭔가 거창한게 들어있을 것 같지만, 실상은 서브모듈 루트 디렉토리의 경로원격 저장소의 주소를 관리하고 있는 게 전부입니다.

gitmodules.png
▲ .gitmodules 파일의 내용

이 파일을 직접 만들고 수정해도 되지만, GIT 서브모듈 명령어를 이용하여 이 파일을 관리할 수 있습니다.

git submodule add {서브모듈 원격 저장소 주소} {서브모듈 루트 디렉토리 경로}

서브모듈 루트 디렉토리 경로는 Master Repository의 루트로부터 상대경로로 입력하도록 합니다.

이렇게 추가하면 빈 서브모듈 루트 디렉토리가 생성됩니다. Master Repository에서 Commit을 하면 이제부터 등록한 서브모듈이 Master Repository에서 Tracking되기 시작합니다.


서브모듈 업데이트

Master Repository를 Clone하면 Slave Repository의 루트 디렉토리는 비어있는 상태로 저장이 됩니다. 이는 비정상적인 상황이 아니며, 서브모듈을 사용하더라도 Repository간 독립성이 유지되기 때문에 발생하는 현상입니다. (즉, Slave Repository만 따로 Clone해서 독자적으로 작업을 할 수도 있습니다.)

.gitmodules 파일이 올바르게 작성되어 있는 경우, 다음 명령어를 입력하여 서브모듈의 내용을 가져올 수 있습니다.

git submodule init
git submodule update

업데이트를 실행하면 서브모듈의 내용을 지정된 위치로 Clone하고, Master Repository에서 마지막으로 Tracking한 위치로 Checkout이 됩니다.

즉, Slave Repository의 HEAD가 경우에 따라서 master에 위치하지 않는 경우도 있습니다.

이는 Master Repository에서는 Slave Repository의 Checkout도 역시 지속적으로 추적하며 관리해야 하는 대상이기 때문에 나타나는 현상입니다. Master Repository에서 Commit은 Slave Repository의 특정 상태를 전제로 이루어지는 것임을 고려하면, 왜 Slave Repository의 Checkout도 추적의 대상이 되는지 이해할 수 있을 것입니다.

원격 저장소를 Clone할 때 다음과 같이 recursive 옵션을 주면 포함된 서브모듈까지 함께 Clone할 수 있습니다. 즉, 원격 저장소를 Clone했는데 .gitmodules파일이 포함되어 있는 경우 서브모듈 초기화 및 서브모듈 업데이트를 자동으로 수행해 줍니다.

git clone --recursive {원격 Repository 주소}


서브모듈에서의 Commit

Master Repository에서 Commit을 할 때, Slave Repository의 변경사항이 있는 경우 Master 및 Slave 각각 두 번의 Commit을 해 주어야 합니다. 이 때, Commit은 반드시 Slave → Master의 순서로 이루어져야 합니다.

Master → Slave의 순서로 Commit을 한 경우, Master Repository에서 git status를 쳐 보면 변경사항이 또 있다는 메시지를 보게 될 것입니다.

Slave Repository는 Master Repository가 바라볼 때 Abstraction되는 방식으로 관리됩니다. 즉, Master Repository에서 Commit을 할 때 Slave Repository의 변화는 1개 변경사항으로 축약되어 추적(Tracking)됩니다.

쉽게 말해서, Slave Repository에서 파일을 100개 바꾼 뒤 Commit을 하고, 다시 Master Repository에서 Commit을 할 때는 이 바꾼 100개 파일이 모두 각각 Tracking되는 것이 아니라, Slave Repository의 HEAD가 무엇으로 변경되었는지에 대한 정보만 기록이 됩니다.

Master에서는 Commit은 Slave의 HEAD 위치를 추적하므로, 이 정보를 토대로 Master에서 Checkout을 할 때 Slave Repository를 그에 맞는 상태로 변경할 수 있는 것입니다.



Articles

1 2 3 4 5 6 7