Git Submodule 대 Subtree | adam-p

ko생성일: 2025. 10. 23.갱신일: 2025. 10. 23.

git subtree와 submodule 사이에서 선택할 때 고려할 점을 간단히 정리합니다. 외부 코드를 사실상 복사해 두고 드물게만 갱신할 때는 subtree, 외부성을 명시하고 수정/푸시까지 할 때는 submodule을 권장합니다.

가끔 git submodule이나 subtree(혹은 아무것도 사용하지 않기) 중에서 선택해야 할 때가 있거나, 동료들이 이에 대해 물어보곤 합니다. 그 빈도가 아주 높지는 않아서 매번 몇 가지 세부 사항을 잊어버리고 기억을 되살려야 하죠. 그래서 동료들과 공유하고 미래의 제 자신을 돕기 위해 이 메모를 적었습니다. 다른 분들께도 어느 정도 도움이 되길 바랍니다.

주의: 제 경험이 아직 많지는 않습니다. 둘 다 한두 번씩만 써 봤습니다. 그리고 이 글은 명령/도구 사용법 매뉴얼이 아니라, 그 사이에서 선택할 때 참고할 수 있는 간단한 도우미입니다.

요약: 외부 코드를 사실상 '잊고' 지내고 싶거나 드물게만 업데이트할 생각이라면 subtree가 낫습니다. 코드가 외부 것이라는 사실을 잊고 싶지 않다, 혹은 그 코드를 편집해서 푸시할 수도 있다고 본다면 submodule이 더 좋습니다.

조사하면서 submodule에 대한 불평을 많이 봤고, 막연히 subtree가 "더 낫다"는 인상을 갖고 있었지만, 써 보니 submodule이 제자리가 분명히 있더군요.

subtree를 사용하면, 본질적으로 원격 코드베이스를 내 파일 구조 안으로 복사해 넣는 것입니다. 그 시점의 자동 커밋 메시지가 원격 커밋 해시를 기록해 주지만, 그 외에는 리포지토리 어딜 봐도 a) subtree 작업이 있었다는 사실, b) 원격 리포지토리가 무엇이었는지, c) 그 원격 리포지토리의 커밋이 무엇이었는지에 대한 표시가 없습니다.

그 후로는 subtree 코드에 대한 변경이 리포지토리의 다른 어느 곳과 마찬가지로 취급됩니다. 코드를 git subtree push, git subtree pull 할 때는 약간 기묘한 Git 디렉터리 슬라이싱을 수행합니다(예전에 기존 리포지토리의 하위 디렉터리만 떼어서, 그 디렉터리의 파일 커밋 기록을 유지한 채 새 리포지토리를 만드는 데 써 본 적이 있습니다). 괜찮긴 하지만 좀 투박합니다.

이는 submodule과는 대조적입니다. submodule에서는 원격 리포지토리의 코드가 복사되지는 않습니다. 대신 원격 리포지토리의 URL, 파일 구조 내 위치, 사용할 원격 리포지토리의 커밋이 기록됩니다. 리포지토리를 클론할 때는 서브모듈 의존성(들)을 별도로 클론해야 합니다(git submodule init+git submodule update 또는 git clone --recurse-submodules). 서브모듈은 파일 구조 안에서 자체 .git 디렉터리를 가진 별도의 리포지토리가 됩니다. 예를 들어 서브모듈 디렉터리에서 git status를 실행하면 바깥 리포가 아니라 서브모듈 코드의 상태를 알려 줍니다. 서브모듈 리포 디렉터리를 업데이트하면 바깥 리포에서 추적하는 서브모듈의 커밋이 바뀌고, 그 변경을 바깥 리포에서 커밋합니다.

서브모듈을 별개의 엔티티로 다루는 것은 쉽습니다. 평소 하던 대로 브랜치 분기, 커밋, 푸시를 하면 됩니다(이때 원격은 바깥 리포가 아니라 서브리포의 원격입니다).

subtree를 클론하는 건 별도 단계가 없어서 더 쉽긴 하지만, 그게 그렇게 큰 장점은 아닙니다. 서드파티 코드를 벤더링할 때는 submodule이 실제 복사를 해 주지 않기 때문에 곤란합니다1 (서드파티 코드를 먼저 포크한 다음 그 포크를 서브모듈로 잡는 경우는 예외).

그래서 결정 기준은 대략 이렇습니다:

  • 외부 리포에서 코드를 한 번만 가져와 복사해 두고 싶거나, 가끔씩만 pull 할 생각이라면 subtree를 쓰세요.
  • 외부 리포와의 관계를 리포지토리 안에 아주 명시적으로 드러내고 싶거나, 내 리포의 컨텍스트 안에서 서브모듈 코드를 수정한 뒤 외부 리포로 푸시할 의도가 있다면 submodule을 쓰세요.

  1. 벤더링 정책과 의존성 관리 시스템에 따라 다릅니다.↩︎