최근 개인 깃허브 저장소를 정리할 필요성을 느꼈다. 생각 없이 commit 하고 push 할 때는 몰랐지만, 정신 차리고 보니 충분히 그룹화시킬 수 있는 소스들이 무질서하게 쌓여있는 걸 보면서 깔끔하게 정리해야겠다는 생각을 하게 되었다.
오래된 코드지만 삭제하기는 싫고, 기록했던 내용을 보관하고 싶다는 마음에 방법이 없을까 찾아보던 중 git에서 제공하는 subtree라는 기능에서 답을 찾을 수 있다.
1. Subtree 란
subtree는 git 저장소 내부에 또 다른 저장소를 두어 관리할 수 있게 도와주는 기능이다. 이 기능을 사용하면, 저장소 내부에 같은 주제(혹은 목적)를 가진 저장소들을 위치시켜 통합적으로 관리할 수 있다.
내 경우를 예로 들면, 프로그래밍 테마 별로 깃허브 저장소를 그룹화시켰다. React, NodeJS, Flutter, Go, Solidity 등의 저장소를 새로 만들고, 기존에 올려둔 저장소들을 새로 만든 저장소 내부에 매핑시켰다.
subtree를 사용하기 전까지만 해도 대략 50개 가까웠던 저장소를 지금 23개까지 줄일 수 있었다.
2. Subtree vs Submodule
앞서 간단히 subtree에 대해 알아보았다. 본격적인 사용 방법을 공유하기 전에 조금 더 subtree란 정확히 어떤 개념이고, 더불어 비슷한 기능인 submodule과 어떤 차이점이 있는지 짧게나마 공유하고 싶다.
2.1. Subtree
subtree는 여러 저장소를 '통합'하는 개념이다. 부모에 해당하는 상위 저장소에 자식 저장소를 '등록'하고 '추가'하는 형태다. subtree에 등록된 내부 저장소에 변경이 있으면, 상위 저장소에 기록된다. 저장소가 subtree로 등록되면, 실제 소스코드는 카피되어 저장된다.
2.2. Submodule
submodule은 하나의 git 저장소 안에 다른 저장소를 '연결'시키는 개념이다. 메인이 되는 저장소에 submodule로 등록되면, 연결된 저장소를 '참조'하는 형식으로 동작한다. 이러한 원리로 만약, submodule로 등록된 저장소에 변경사항이 있다면, 메인이 되는 저장소에 해당 업데이트 내역이 즉각 반영되는 것이 아니라 변경 내역을 받아와 새롭게 갱신(commit과 push)을 진행해야 한다.
2.3. 정리
subtree과 submodule 모두 흩어져 있는 저장소를 하나로 묶어 통합 관리하는 개념이다. 하지만, subtree는 부모-자식과의 관계처럼 상위 저장소에 다른 저장소가 카피되어 등록되는 형태에 가깝고, submodule은 컨트롤 타워와 같은 메인 저장소에 다른 저장소가 링크되어 변동 내역을 참조하는 구조에 가깝다.
이러한 차이에서 subtree는 여러 저장소를 하나로 묶어 하나의 개별 저장소로 이용하는 목적에서 사용되며, submodule은 기존에 하나였던 저장소를 여러 개의 개별 저장소로 나누고, 내부 변경 이력에 대한 추적 및 참조 기능만 통합하는 목적으로 사용된다.
내가 만든 저장소의 목적, 혹은 성격에 따라 subtree를 사용해야 할지, submodule을 사용해야 할지 선택적으로 사용할 수 있다.
3. 저장소 병합 방법
이제 본격적으로 오늘 포스트의 주제인 subtree를 사용한 저장소 병합 내용을 공유하고자 한다. 병합은 아래와 같은 단계로 진행할 수 있다.
- 메인 저장소 생성, 소스코드 clone
- subtree 등록
- 기존 repo 삭제
3.1. 메인 저장소 생성, 소스코드 clone
먼저, 내가 저장소들을 묶어줄 상위 저장소를 생성한다. 깃허브에 새 저장소를 등록하고, 원하는 경로에 clone 받을 디렉토리를 지정한다.
# 병합이 이루어질 디렉토리 생성 및 경로 이동
mkdir ~/path/merge-dir
cd ~/path/merge-dir
# 병합할 저장소 Clone
git clone https://repo-url.git
3.2. subtree 등록
subtree 등록 명령어는 아래 코드블록을 참조하면 된다. --prefix 플래그에 등록할 하위 저장소의 이름을 지정한다. 이름은 저장소에 등록된 이름과 달라도 되니, 원하는 디렉토리 이름을 써주면 된다.
중요한 건 가지고 오고자 하는 하위 저장소의 주소와 브랜치 이름이다. git clone이나 git pull 명령어를 생각하면 이해하기 쉽다.
# subtree 등록 명령어 템플릿
git subtree add --prefix=[등록할 디렉토리 이름] [가지고 오고자하는 저장소 주소] [병합할 저장소의 브랜치]
# 실제 실행 명렁어
git subtree add --prefix=merge-dir https://github.com/user-name/test-progject.git master
등록에 성공하면, 다음과 같은 실행 로그를 확인할 수 있다. 나의 경우 저장소 주소의 master 브랜치 내용을 메인 저장소 내부 'merge-dir' 디렉토리로 등록해 내용을 받아왔다.
# 실행 결과
git fetch https://github.com/trustnloveu/user-name/test-progject.git master
remote: Enumerating objects: 202, done.
remote: Counting objects: 100% (202/202), done.
remote: Compressing objects: 100% (114/114), done.
remote: Total 202 (delta 102), reused 176 (delta 76), pack-reused 0
Receiving objects: 100% (202/202), 31.80 KiB | 7.95 MiB/s, done.
Resolving deltas: 100% (102/102), done.
From https://github.com/trustnloveu/user-name/test-progject
* branch master -> FETCH_HEAD
Added dir 'merge-dir'
# git 로그 확인
git log
commit 8ce46c9eb7ef34783971e83c78 (HEAD -> master)
Merge: d25a4fb a58c4b0
Author: name <trustnloveu@email.com>
Date: Sat Feb 11 17:35:39 2023 +0900
Add 'merge-dir/' from commit 'a58c4b07676403cb1c094697468...'
git-subtree-dir: merge-dir
git-subtree-mainline: d25a4fb83edc79a43fcbf6f960...
git-subtree-split: a58c4b07676403cb1c094697468...
4. 마치며
위 과정을 잘 진행했다면, 저장소 병합은 끝났다. 병합이 이루어지면서 기존 소스코드와 커밋이력 역시 카피되어 저장되었을 것이다. 이제 깃허브에 남아있는 저장소들을 과감히 삭제하면 된다.
'Programing > Git & Github' 카테고리의 다른 글
[Github] 깃허브 CLI 로그인 이슈, Access Token - 'fatal: Authentication failed for ...' (0) | 2023.02.11 |
---|---|
[Gitlab] Ubuntu에서 Gitlab 설치 (gitlab-ce) (0) | 2022.11.06 |
댓글