GitHub 레포지토리 합치기와 분리하기: git subtree 완벽 가이드




프로젝트를 진행하다 보면 여러 레포지토리를 하나로 합치거나, 반대로 하나의 큰 레포지토리를 여러 개로 분리해야 할 때가 있습니다. 이 글에서는 git subtree 명령어를 활용해 레포지토리를 자유자재로 통합하고 분리하는 방법을 알아보겠습니다.

들어가며: 왜 레포지토리를 합치거나 분리할까?

합치는 경우 (Monorepo)

  • 관련된 여러 프로젝트를 한 곳에서 관리하고 싶을 때
  • 공통 코드나 설정을 쉽게 공유하고 싶을 때
  • 의존성 관리를 단순화하고 싶을 때

분리하는 경우 (Multi-repo)

  • 특정 모듈을 독립적인 라이브러리로 배포하고 싶을 때
  • 팀별로 레포지토리를 분리해서 관리하고 싶을 때
  • 레포지토리가 너무 커져서 가볍게 만들고 싶을 때

git subtree란?

git subtree는 Git에 기본 내장된 명령어로, 다른 레포지토리를 현재 레포지토리의 하위 디렉토리로 포함시키거나, 특정 디렉토리를 별도의 레포지토리로 분리할 수 있게 해줍니다.

비슷한 기능인 git submodule과 비교하면 다음과 같은 차이가 있습니다.

특성subtreesubmodule
코드 포함 방식완전히 복사됨링크로 연결
관리 복잡도단순함복잡함
clone 시자동 포함별도 명령 필요
커밋 히스토리통합됨분리됨

대부분의 경우 subtree가 더 직관적이고 관리하기 쉽습니다.

여러 레포지토리를 하나로 합치기

시나리오

frontend, backend, common 세 개의 레포지토리를 my-project라는 하나의 모노레포로 합친다고 가정합니다.

1단계: 새 레포지토리 생성

mkdir my-project
cd my-project
git init

2단계: 첫 번째 커밋 생성

echo "# My Project" > README.md
git add README.md
git commit -m "Initial commit"

3단계: 각 레포지토리를 subtree로 추가

# frontend 레포지토리 추가
git subtree add --prefix=frontend https://github.com/username/frontend.git main

# backend 레포지토리 추가
git subtree add --prefix=backend https://github.com/username/backend.git main

# common 레포지토리 추가
git subtree add --prefix=common https://github.com/username/common.git main

4단계: 결과 확인 및 push

# 구조 확인
ls -la

# GitHub에 push
git remote add origin https://github.com/username/my-project.git
git push -u origin main

최종 구조

my-project/
├── README.md
├── frontend/
│   └── (frontend 레포의 모든 파일)
├── backend/
│   └── (backend 레포의 모든 파일)
└── common/
    └── (common 레포의 모든 파일)

각 폴더에는 원본 레포지토리의 커밋 히스토리가 그대로 보존됩니다.

하나의 레포지토리를 여러 개로 분리하기

시나리오

my-project 모노레포에서 common 폴더를 독립적인 레포지토리로 분리한다고 가정합니다.

1단계: subtree split으로 브랜치 생성

cd my-project
git subtree split --prefix=common -b common-branch

이 명령은 common 폴더의 히스토리만 추출해서 common-branch라는 브랜치를 생성합니다.

2단계: 새 레포지토리 생성 및 코드 이동

# 새 디렉토리 생성
cd ..
mkdir common-repo
cd common-repo
git init

# 분리한 브랜치 가져오기
git pull ../my-project common-branch

3단계: GitHub에 push

git remote add origin https://github.com/username/common.git
git push -u origin main

4단계: 원본 레포에서 폴더 제거 (선택사항)

분리 후 원본 모노레포에서 해당 폴더를 제거하고 싶다면:

cd ../my-project
git rm -r common
git commit -m "Remove common folder (moved to separate repo)"
git push

실전 팁

1. 커밋 히스토리 보존 확인

합치거나 분리한 후에는 반드시 git log로 히스토리가 제대로 보존되었는지 확인하세요.

git log --oneline --graph

2. 원격 레포지토리 정리

합친 후 기존 레포지토리들을 어떻게 처리할지 결정해야 합니다.

  • Archive: 읽기 전용으로 보관 (GitHub Settings → Archive)
  • Delete: 완전히 삭제
  • README 업데이트: 새 레포지토리로 이동했다는 안내 추가

3. squash 옵션 활용

히스토리를 보존하지 않고 하나의 커밋으로 합치고 싶다면 --squash 옵션을 사용합니다.

git subtree add --prefix=frontend https://github.com/username/frontend.git main --squash

4. 이후 업데이트 반영하기

원본 레포지토리에 변경사항이 생겼을 때 가져오려면:

git subtree pull --prefix=frontend https://github.com/username/frontend.git main

주의사항

  1. 충돌 가능성: 합칠 때 파일명이 겹치면 충돌이 발생할 수 있습니다. 미리 구조를 확인하세요.
  2. 대용량 레포지토리: 히스토리가 많은 레포지토리를 합치면 시간이 오래 걸릴 수 있습니다.
  3. GitHub UI 미지원: 이 작업들은 GitHub 웹 인터페이스에서는 할 수 없습니다. 반드시 로컬 Git 클라이언트를 사용해야 합니다.
  4. 팀 공유: 모노레포 전환 시 팀원들에게 미리 공지하고, 기존 레포지토리의 PR/이슈를 정리하세요.

마치며

git subtree를 활용하면 프로젝트 구조를 유연하게 변경할 수 있습니다. 모노레포와 멀티레포 각각의 장단점을 고려해서 프로젝트에 맞는 구조를 선택하시기 바랍니다.




댓글 남기기