Git submodule로 활동 기록 정리하기


프로젝트를 진행할 때 다른 프로젝트를 활용해야할 때가 있다. 이 경우 가져다 쓰는 프로젝트를 Git을 통해 관리하지 않고 서브모듈submodule을 사용해 불필요한 코드의 업로드를 최소화하는 방법이 있다. 이 글에서는 서브모듈을 활용해서 여러 레포지토리에 분산되어 있는 활동들을 한 곳에 모아보는 방법을 소개한다.

가장 처음 떠오르는 것은 아카이브 저장소를 만든 다음, 그 레포지토리에 지금까지 활동한 것을 다시 Git을 통해 관리하는 것이다. 한땀한땀 폴더를 복사/붙여넣기한 뒤에 관리할 수 있겠다. 이 경우, 본래 저장소와 아카이브 저장소에 차이가 생기는 순간 재앙이 시작된다. 두 소스 간에 충돌이 발생하고.. -f를 붙여 강제로 커밋하는 등 까다로운 상황이 자주 발생할 수 있다. 🤯

서브모듈을 사용하면 이 걱정을 덜 수 있다. 원본 코드를 복사-붙여넣기할 필요가 없다. 또, 기존 코드에 변동사항이 발생하더라도, 간단한 Git 명령어를 통해 아카이브 저장소를 손쉽게 동기화할 수 있다! 🥳

Submodule을 사용해서 Github에 업로드한 결과

아카이브 저장소 준비하기

우아한테크코스에서 해결한 미션들을 하나의 저장소에 모으고 싶다고 하자. 우선 아카이브 저장소를 만들어야 한다. 이 글에서는 Github를 활용한다.

아카이브용 저장소를 만들자! 🤸🏻‍♂️

로컬에서 서브모듈 생성하기

저장소를 만들었다면, 로컬에서 서브모듈을 만들어 보자. 우선 해당 깃 저장소를 나의 컴퓨터로 가져와야 한다.

  • 지금부터 명령어에서 등장하는 중괄호 {}는 각자 자신에게 맞는 상황의 주소나 값을 넣어주면 된다.
  • 대괄호 []는 필요할 때에 선택적으로 채운다. 명시하지 않아도 되나 이 경우 기본값이 있다(optional).

git clone {repository-url} [{path}]

path를 지정해 주면 해당 이름을 가진 폴더가 생성되며, 그렇지 않으면 저장소의 이름이 기본적으로 설정된다. 이제 cd를 통해 복제한 저장소 폴더에 들어간 뒤, 아래와 같은 명령어로 외부 저장소를 참조해 서브모듈을 만들어 보자.

git submodule add [-b {branch-name}] {repository-url} [{path}]

만약 https://github.com/donghoony/woowacourse-level-1-racingcar 저장소의 donghoony-step-2 브랜치를 서브모듈로 사용하고 싶고, woowacourse/level-1-racingcar라는 폴더 안에 저장하고 싶다면 아래와 같이 작성하면 된다. 위 명령어의 변수명과 비교하면서 읽어 보자.

git submodule add -b donghoony-step-2 https://github.com/donghoony/woowacourse-level-1-racingcar woowacourse/level-1-racingcar

서브모듈을 추가하면 해당 브랜치의 HEAD를 참조한다
woowacourse/level-1-racingcar 디렉토리가 추가되었고, 내부 소스가 존재한다.

Github에 서브모듈 커밋을 푸시하기

이제 로컬 변경사항이 생겼으니, 이를 커밋하고, 원격 저장소에 푸시해야 한다. 서브모듈 폴더 내부에도 git 설정 파일이 존재하기 때문에, 해당 소스코드 폴더로 들어가지 않고 외부(아카이브 폴더)에서 진행함에 유의하자.

git commit -m "{commit-message}
git push {upstream} {branch-name} // upstream은 별다른 조치를 하지 않았다면 origin이다.

커밋 메시지를 작성하고, 나의 브랜치에 올바르게 커밋하자

커밋과 푸시를 완료했다면 Github에 변경 사항이 적용된다. 지금까지 보았던 디렉토리랑은 다르게, 파란 글씨로 디렉토리 이름과 참조 저장소의 커밋 해시가 함께 적혀있다. 추가적인 복사-붙여넣기 없이 나의 활동을 기록할 수 있게 되었다!

Github에서 submodule이 연동된 모습. 클릭하면 원본 저장소의 참조 커밋으로 이동한다

서브모듈에 추가 커밋 사항 반영하기

원본 저장소에 변경이 일어날 때마다 아카이브 저장소도 동기화해야 한다. 서브모듈은 만들어질 때의 커밋을 기준으로 참조하기 때문이다. 이 경우는 아래와 같은 명령어를 사용해 동기화를 진행해 보자.

git submodule foreach git pull

만약 서브모듈을 만들고 나서, 이후에 삭제한 뒤 변경사항이 생겨 다시 복제해온 경우에는 서브모듈 내부에 소스가 존재하지 않을 것이다. 이 때에는 pull하기 전에 init을 통해 서브모듈 정보를 받아와야 한다.

git submodule init
git submodule update

실험을 위해 update-test라는 서브모듈을 만들고 푸시했다. 이후에 update-test 원본 저장소에 text.txt 파일이 추가된 상태이다(아카이브 저장소에는 반영되지 않음). 이때 git submodule foreach git pull을 통해 각 서브모듈 정보를 최신으로 업데이트할 수 있다. 서브모듈을 만들 때 참조한 브랜치의 HEAD를 가져옴에 유의하자.

update-test에서 변경이 일어난 뒤, 아카이브 저장소에 변경사항을 적용한다.

로컬 저장소에 변동이 생겼으니 커밋-푸시하는 것도 잊지 말자!


서브모듈과 관련된 정보는 .gitmodules에 정리돼 있다. 이곳에서 브랜치 정보를 바꾸는 등 여러가지를 해볼 수 있다. remote와 관련된 사항을 변경했을 때에는 git submodule update --remote도 사용해야 한다!

나는 이곳에서 활동을 차곡차곡 쌓으려고 한다! 각 폴더에 readme를 배치한다면 더 풍부한 저장소가 될 듯하다 🤗 꾸준히 기록하는 것이 어렵다면, 이렇게라도 나의 활동들을 체계적으로 분류해두는 건 어떨까? 나중에 돌아보기에도 편리하고, 다른 사람에게 활동 기록을 한 눈에 소개하기에도 좋을 듯하다 👍

Categories