Today I../Today I Learned

[Git] git submodule

HJChung 2021. 12. 19. 14:42

배경

여러 프로젝트(main project)에서 사용하는 공통 모듈(sub project)이 있을 때, main project와 sub project들은 어떻게 git으로 관리할 수 있을까? 이 sub project는 어느 repo에 저장이 되는 것이 좋을까?

이럴 때, sub project가 독립적인 Repo에서 버전관리 되고, 이 모듈을 사용할 프로젝트인 main project들에는 원하는 폴더에 이 sub project 들이 연결되어 있어서 사용할 수 있으면 좋을 것이다. 

출처: https://www.youtube.com/watch?v=TAe4uZqYt6c

이런 기능 뿐만 아니라, sub project에 여러 버전이 있을 때,  특정 버전과 이를 사용할 main project의 디렉토리를 연결시켰다가, 

또 다른 버전이 준비되었을 때, 손 쉽게 다른 버전으로 변경할 수 있다면 버전 관리에서 좋을 것이다. 

정리하면, 

  • main project에서는 sub project의 내용을 관리하지 않고, 각 각 독립적으로 git 을 통해 버전관리가 되고 있다. 
  • main project에는 sub project의 어떤 버전을 의존할지, 어떤 하위 폴더에 넣을 지만 어떤 파일에 명세로 작성하여 관리한다.
  • 필요할 때 sub project의 해당 버전을 가져다 main project 내 적절한 폴더에 위치시켜 사용한다.

라는 기능들이 필요하다. 

이러한 기능을 모두 제공하는 Git submodule이라는 것에 대해 실제 tutorial 형식으로 실습을 해보며 정리해 보고자 한다. 

 

Quick Stark

1. 환경 구성 

아래 3개의 repo를 생성해보자. 

main proejct에서는 sub1 project repo, sub2 project repo를 사용한다. 

그리고 sub1proejct-submodule-practice/main.py

print("hello world. this is sub1")

sub2proejct-submodule-practice/main.py

print("hello world. this is sub2")

를 생성해준 후, 각 repo에 commit, push 한다. 

 

이렇게 준비 한 후 어떻게 사용되는지 이제 시작해 봅시다!

 

2. Clone Submodules

main proejct의 /lib에 sub1 project repo 코드들을 복제해서 넣을 것이며, main proejct의 /module 에는 sub2 project repo 을 복제해서 넣을 것이다.

즉, sub1, sub2 가 복제되어서 main의 sub module로서 역할하게 된다. 

 

정리하자면 
mainproject-submodule-practice
/lib
에 sub1project-submodule-practice를 clone 하고자 함. 
/module 
에 sub2project-submodule-practice를 clone 하고자 함. 

단, 주의할 점이 있다. submodule은 main project와 sub project가 부모 자식 관계를 가지고 연결되어 있다. 따라서 외부로 부터 새로운 정보를 받아 갱신해야 할 때 (clone, pull, update 등)에는 모든 작업 순서가 main project 먼저, sub project 나중이어야 한다. 생각해 보면 당연하다. 부모가 존재해야 자식도 존재할 수 있기 때문이다.

from https://pinedance.github.io/blog/2019/05/28/Git-Submodule

 

위의 주의사항대로, 우선 main project root 경로에서 clone submodule 과정이 수행되어야 한다. 

cd mainproject-submodule-practice

git submodule add [sub module remote git address] [main module directory]

(ex. git submodule add https://github.com/Gracechung-sw/sub1project-submodule-practice lib)
(ex. git submodule add https://github.com/Gracechung-sw/sub2project-submodule-practice module)

 

그러면 mainproject-submodule-practice 내에 /lib, /module directory,  .gitmodules가 생성된다. 

 

mainproject-submodule-practice/lib와 sub1proejct-submodule-practice의 git log를 확인해볼까?? 

git log가 동일하다. 즉, clone이 되어서 들어갔다는 것을 확인 할 수 있다. 

 

.gitmodules는 무슨 파일일까? mainproject-submodule-practice 에 생성된 이 파일을 열어보면 아래와 같은 정보가 있을 것이다. 

sub project가 main project에서 위치할 폴더명과 git repo 주소가 적혀있다. 즉, sub project에 대한 명세서인 것이다. 
자세한 내용은 https://git-scm.com/docs/gitmodules을 참고할 수 있다. 

[submodule "lib"]
	path = lib # lib 이라는 폴더에는 
	url = https://github.com/Gracechung-sw/sub1project-submodule-practice # 이 주소가 clone 된다. 
[submodule "module"]
	path = module # module이라는 폴더에는 
	url = https://github.com/Gracechung-sw/sub2project-submodule-practice # 이 주소가 clone 된다. 
    
# 와 같은 submodule에 대한 정보가 들어있다.

위의 과정으로 변경된 main project를 커밋해주자. 

git diff --cached
git commit -m 'submodule added'

 

3. Update Submodule

여기까지 하면 .gitmoudules 정보를 main project에서 가지고 있기 때문에 언제든지 sub1 project, sub2 proejct와 연결할 수 있다. 

 

그럼 sub moduule을 업데이트시, 어떻게 main project에 반영시킬 것인가?

 

sub1/ main.py 을 아래와 같이 업데이트 시켜보자. 

print("hello world. this is sub1")
print("Update sub1") # Add this
git add .; git commit -m 'sub1 main.py updated'; git push origin main

 

그럼 main project에도 sub1 proejct의 code update를 반영하려면 어떡하면 될까?

그냥 main project root에서 git pull하면 될까? 아니다. 

왜냐하면 main project의 /lib에 연결되있는 것은 sub proejct로 별도의 독립된 프로젝트 이기 때문이다. 그래서 /lib 경로에 가서 git pull 을 해야한다. 

cd lib
git pull

 

 

remote: Enumerating objects: 5, done.
remote: Counting objects: 100% (5/5), done.
remote: Compressing objects: 100% (3/3), done.
remote: Total 3 (delta 0), reused 3 (delta 0), pack-reused 0
Unpacking objects: 100% (3/3), done.
From https://github.com/Gracechung-sw/sub1project-submodule-practice
   0ccbfe0..2848414  main       -> origin/main
Updating 0ccbfe0..2848414
Fast-forward
 main.py | 3 ++-
 1 file changed, 2 insertions(+), 1 deletion(-)

그리고 /lib의  main.py를 확인해보면 코드가 바뀌어 있는 것을 알 수 있다. 

문제가 없다는 걸 확인하면 main project root에서 git commit, git push 을 진행한다. 

 

4. git submoodule 명령어들

1) git submodule update

그런데.... 매번 submoduel의 코드가 바뀔 때마다 main project에서는 해당 경로에 들어가서 git pull 하고... 를 반복해야 할까?

너무 비효율적이고 귀찮다.

이를 한 번에 해결하는 기능이 있다. 

git submodule update --remote

 

 --remote 옵션은 '원격 저장소의 최신 정보를 지역 저장소의 최신으로 업데이트 시켜라' 라는 뜻이다. 

이 한줄이면 위의 <3.Update Submodule>의 과정을 한 번에 해결할 수 있다. 

※ 위의 명령어를 입력했을 때, 
fatal: Needed a single revisionUnable to find current origin/master revision in submodule path ~
이런 에러가 발생할 수도 있다. 
그 이유는 위의 명령어를 실행할 branch가 master로 되어 있는데, 내가 작업을 하고 있는 branch는 main이기 때문이다. 
이럴 경우 .gitsubmodules 파일에 들어가서 branch를 지정해주면 된다. 
[submodule "lib"]
	path = lib
	url = https://github.com/Gracechung-sw/sub1project-submodule-practice
	branch = main
[submodule "module"]
	path = module
	url = https://github.com/Gracechung-sw/sub2project-submodule-practice
	branch = main​
git submodule update --remote --recursive

 

 --recursive 란, submodule도 자신의 submodule을 가지고 있을 수 있는데, 그 하위에 있는 모든 것을 update한다는 의미이다. 

 

2) git submodule summary

내  main project local repo의 sub module(/lib)버전과, sub module의 remote repo의 버전이 같은지/다른지 확인해 보고자 할 때 사용할 수 있는 명령어는, 

git submodule summary

 

3) git submodule foreach

foreach를 사용하면 일괄적으로 foreach 다음에 온 명령어를 한 번에 각 서브모듈에 Git 명령을 내릴 수 있다.

git submodule foreach "git log --oneline; ls -al; ...등 다양한 명령어"

 

그 외의 많은 git submodule 명렁어들은

git submodule --help

 

을 통해 살펴볼 수 있다. 

 

 

 

마무리

지금까지 매우 간단한 submodule 추가 및 업데이트 과정만 살펴보았다. 

시간이 부족하여 (레알인가.... '글또 글 쓸거임 내일부터' 라고 미루던 내 자신 눈감아) 이 정도밖에 정리해보지 못했지만 

 

 Git submodule 사용하기 블로그에 위의 예시 말고도 처음부터 git submodule 명령어들을 사용해서 

1. .gitmodules에 명시되어 있는대로 sub project를 clone 해오고, 

2. main project가 업데이트되었을 때, main project와 sub project를 update하는 법 

3. main project에 새로운 sub project를 추가하는 법

4. main project에서 sub project를 수정하고 main, sub remote repo에 반영하는 법 

5. 그 외 유용한 기능 설정

등에 대한 설명이 잘 나와있다. 

 

이를 참고하여 추후에 이 포스트도 보충하고자 한다. 

 

 

Reference

저장소 안에 저장소 - git submodule

Git submodule 사용하기

7.11 Git 도구 - 서브모듈