새소식

git

[Git] 깃 서브모듈(Submodule)

  • -

Submodule

Git Submodule은 하나의 저장소(부모)에 다른 저장소(자식)를 두고 관리하기 위한 도구로, 하나의 프로젝트에서 다른 프로젝트를 함께 사용해야 하는 경우에 많이 사용한다.

나는 프로젝트는 public repo로 관리하고, 애플리케이션의 중요한 정보들이 담기는 .yml, .properties는 private repo에 따로 관리하고 싶어서 이를 적용했다.

간단해보였지만 의외로 주의해야 할 점이 많아서 기록해두려 한다.

프로젝트에 Submodule 적용하기

1. Public, Private Repository 생성

먼저 Public Repository 하나와 Private Repository 하나를 생성한다.

Public Repository에는 프로젝트를, Private Repository에는 프로젝트에서 숨겨야하는 중요한 설정 파일들(application.yml 등)을 넣는다.

이 때, Private Repository에서 관리할 파일들은 Public Repository에서 제거해준다.

2. Public Repository에 Submodule 등록

Public Repository에 다음과 같이 서브 모듈을 등록해준다.

$ git submodule add [submodule로 등록할 repo 주소] [submodule 디렉토리를 둘 경로]
Cloning into ...
remote: Enumerating objects: 11, done.
remote: Counting objects: 100% (11/11), done.
remote: Compressing objects: 100% (11/11), done.
remote: Total 11 (delta 0), reused 11 (delta 0), pack-reused 0
Receiving objects: 100% (11/11), done.

정상적으로 등록이 완료되면 서브 모듈을 등록한 repository 최상위에 .gitmodules 파일이 생성되고, 지정한 경로에 submodule repository 디렉토리가 생성된다.

.gitmodules 파일 내부는 다음과 같다.

$ cat .gitmodules
[submodule "submodule 디렉토리 경로"]
    path = submodule 디렉토리 경로
    url = submodule git repository 주소

3. Public Repository Push

submodule 등록을 완료하였으면 이를 commit/push 해야 리모트에 반영된다. Public Repository를 push 하자.

push 한 뒤에 깃허브를 확인해보면 config @ 102f51b와 같이 디렉토리 이름 뒤에 @ commit-id가 붙어있고, 링크로 표시되는 것을 확인할 수 있다.
해당 링크로 접근하면 submodule로 등록된 repository에 접근할 수 있는데, 해당 submodule repository가 private이라면 권한이 없는 유저는 접근할 수 없다.

여기서 표시되는 commit-id는 해당 repository가 참조하는 submodule repository의 commit-id이다.

Submodule이 적용된 프로젝트 clone 하기

처음 submodule이 적용된 프로젝트를 clone 하면, submodule 내부의 파일이 존재하지 않는다.
터미널에서 다음 명령을 통해 submodule을 초기화하고 업데이트한다.

# submodule 초기화
$ git submodule init
Submodule '프로젝트에 적용된 submodule path' (submodule repository url) registered for path '프로젝트에 적용된 submodule path'

# submodule 업데이트
$ git submodule update
Cloning into 'local project의 submodule path'...
Submodule path 'project submodule path': checked out 'submodule commit-id'

submodule이 적용된 프로젝트를 처음 clone 할 때 submodule까지 한번에 clone 할 수 있다. 다음 명령을 이용한다.
$ git clone --recurse-submodules [main-project-url]

update된 submodule repository를 main repository로 가져오기

submodule repository가 업데이트 되었는데 메인 프로젝트 repository에 아직 반영이 안되었을 경우, submodule repository의 변경 사항을 가져와서 작업해야 하는 경우에는 다음 명령을 이용할 수 있다.

$ git submodule update --remote --merge
  • --remote 옵션은 .gitmodules 파일에 정의되어 있는 브랜치의 최신 버전으로 업데이트한다.
  • --merge 옵션은 로컬에서 작업 중인 부분과 원격에 작업된 부분이 다르면, merge까지 진행해준다.

위 명령을 수행하고 나면 메인 프로젝트에 submodule repository의 변경 사항이 적용되었다.
메인 프로젝트 commit/push 시점에 해당 변경 사항을 함께 commit/push 해주면 된다.
로컬에 업데이트한 submodule의 변경 사항을 commit/push 해주지 않으면 remote에는 변경 사항이 적용되지 않은 이전 커밋의 submodule을 참조하고 있을 것이다..

로컬의 submodule repository 변경 내역을 commit/push 하기

submodule repository의 파일에 변경 사항을 커밋하고 싶다면, 먼저 메인 프로젝트에 등록된 submodule repository 디렉토리로 이동한다.

메인 프로젝트에서 해당 디렉토리로 이동하면, 메인 프로젝트가 참조하고 있는 submodule repository의 commit으로 체크아웃 될 것이다.

아래와 같이, 변경 내역을 commit/push 할 submodule repository의 branchcheckout하고, add, commit, push 한다.

# project submodule path로 이동
~/project $ cd [project submodule path]

# main project가 참조하고 있는 submodule의 commit으로 체크아웃 됨.
# commit/push 할 branch로 checkout
~/project/submodule-path[➦ commit-id] $ git checkout main

# add, commit, push 수행하면 된다.
~/project/submodule-path[ main] $ 

submodule repository를 업데이트하고 나면, 메인 프로젝트의 submodule이 참조하고 있는 submodule repository의 commit을 업데이트 해줘야 한다.
메인 프로젝트에서 git submodule update 명령을 통해 submodule이 참조하는 commit을 업데이트 해주자.

submodule repository에 새로운 변경 내역을 업데이트 했지만, 메인 프로젝트에서 git submodule update 명령을 수행하지 않으면, 메인 프로젝트는 여전히 변경 내역이 적용되지 않은 이전 커밋의 버전을 참조한다.
메인 프로젝트에서도 변경 사항을 적용하고 싶다면 꼭 submodule을 업데이트 해주자.

Jenkins 같은 CI/CD 툴을 이용할 때 서브 모듈에 있는 파일이 필요할 수도 있다. 이 경우 서브 모듈에 접근할 수 있는 권한을 줘야한다. (ex: Jenkins의 경우 credentials를 추가해주면 간단하게 해결된다.)

[Git] 깃 서브모듈(Submodule)

포스팅 주소를 복사했습니다

이 글이 도움이 되었다면 공감 부탁드립니다.