Git subtree: Git submodule의 대안

인터넷에는 Git submodule을 사용하지 않아야 하는 이유에 대한 문서로 가득합니다. submodule은 몇 가지 사용 사례에는 유용하지만 여러 단점이 있습니다.

대안이 있습니까? 네, 있습니다! Git을 계속 사용하면서 프로젝트의 소프트웨어 종속성 기록을 추적하는 데 도움이 되는 도구가 (적어도) 두 개 있습니다.

  • Git 하위 트리

  • Google 리포지토리

이 문서에서는 git subtree에 대해 알아보고 완벽하지는 않아도 Git 하위 모듈보다 나은 이유를 살펴보겠습니다.

Git subtree란 무엇이며 왜 사용해야 합니까?

git subtree를 사용하면 하나의 리포지토리를 다른 리포지토리에 하위 디렉터리로 중첩시킬 수 있습니다. Git 프로젝트가 프로젝트 종속성을 관리할 수 있는 몇 가지 방법 중 하나입니다.

전후 Git subtree 다이어그램

git subtree를 고려해야 하는 이유

  • 간단한 워크플로를 관리하기가 쉽습니다.

  • 이전 버전의 Git이 지원됩니다(v1.5.2 이전 버전도 지원).

  • 하위 프로젝트의 코드는 상위 프로젝트의 복제가 완료된 직후에 사용 가능합니다.

  • git subtree의 경우 리포지토리의 사용자가 새로운 것을 배울 필요가 없으며 git subtree를 사용하여 종속성을 관리한다는 사실을 무시할 수 있습니다.

  • git subtree는 Git 하위 모듈처럼 새 메타데이터 파일을 추가하지 않습니다(예: .gitmodule).

  • 다른 곳에 종속성의 리포지토리 복사본을 별도로 가지고 있지 않아도 모듈의 콘텐츠를 수정할 수 있습니다.

대체로 감수할 만하다고 생각하는 단점은 다음과 같습니다.

  • 새로운 병합 전략에 대해 배워야 합니다(예: git subtree).

  • 하위 프로젝트를 위해 업스트림에 코드를 다시 기여하는 것이 조금 더 복잡합니다.

  • 커밋에서 상위 프로젝트 코드와 하위 프로젝트 코드를 혼용하지 않는 책임이 사용자에게 있습니다.

Git subtree를 사용하는 방법

git subtree는 2012년 5월 v1.7.11 이상부터 Git의 스톡 버전에서 사용할 수 있습니다. OSX에서 Homebrew로 설치된 버전에는 이미 하위 트리가 제대로 연결되어 있지만 일부 플랫폼에서는 설치 안내를 따라야 할 수도 있습니다.

git subtree를 사용하여 vim 플러그인을 추적하는 기본적인 예시는 다음과 같습니다.

원격 추적 없이 빠르고 간편한 방법

한 줄짜리를 몇 개만 잘라서 붙이고 싶은 경우 이 문단을 읽어보세요. 먼저 지정된 접두사 폴더에 git subtree를 추가합니다.

git subtree add --prefix .vim/bundle/tpope-vim-surround https://bitbucket.org/vim-plugins-mirror/vim-surround.git main --squash

(일반적인 방법은 하위 프로젝트의 전체 기록을 메인 리포지토리에 저장하지 않는 것이지만 전체 기록을 보존하려면 --squash 플래그를 생략하면 됩니다.)

위 명령을 실행하면 다음과 같은 결과가 출력됩니다.

git fetch https://bitbucket.org/vim-plugins-mirror/vim-surround.git main
warning: no common commits
remote: Counting objects: 338, done.
remote: Compressing objects: 100% (145/145), done.
remote: Total 338 (delta 101), reused 323 (delta 89)
Receiving objects: 100% (338/338), 71.46 KiB, done.
Resolving deltas: 100% (101/101), done.
From https://bitbucket.org/vim-plugins-mirror/vim-surround.git
* branch main -} FETCH_HEAD
Added dir '.vim/bundle/tpope-vim-surround'

여기서 볼 수 있듯이 이 작업은 vim-surround 리포지토리의 전체 기록을 하나의 기록으로 스쿼시하여 merge commit을 기록합니다.

1bda0bd [3 minutes ago] (HEAD, stree) Merge commit 'ca1f4da9f0b93346bba9a430c889a95f75dc0a83' as '.vim/bundle/tpope-vim-surround' [Nicola Paolucci]
ca1f4da [3 minutes ago] Squashed '.vim/bundle/tpope-vim-surround/' content from commit 02199ea [Nicola Paolucci]

잠시 후 업스트림 리포지토리에서 플러그인 코드를 업데이트하고 싶은 경우 git subtree를 풀하면 됩니다.

git subtree pull --prefix .vim/bundle/tpope-vim-surround https://bitbucket.org/vim-plugins-mirror/vim-surround.git main --squash

아주 빠르고 쉽게 할 수 있지만 명령이 약간 길어서 기억하기 어렵습니다. 하위 프로젝트를 원격으로 추가하여 명령을 더 짧게 만들 수 있습니다.

하위 프로젝트를 원격으로 추가

하위 트리를 원격으로 추가하면 더 짧은 형식으로 참조할 수 있습니다.

git remote add -f tpope-vim-surround https://bitbucket.org/vim-plugins-mirror/vim-surround.git

이전과 같이 하위 트리를 추가할 수 있지만 이제 원격을 더 짧은 형식으로 참조할 수 있습니다.

git subtree add --prefix .vim/bundle/tpope-vim-surround tpope-vim-surround main --squash

나중에 하위 프로젝트를 업데이트하는 명령은 다음과 같습니다.

git fetch tpope-vim-surround main
git subtree pull --prefix .vim/bundle/tpope-vim-surround tpope-vim-surround main --squash

업스트림에 다시 기여

이제 로컬 작업 디렉터리의 하위 프로젝트에 수정 사항을 자유롭게 커밋할 수 있습니다. 업스트림 프로젝트에 다시 기여할 때가 되면 프로젝트를 포크하고 다른 원격으로 추가해야 합니다.

git remote add durdn-vim-surround ssh://git@bitbucket.org/durdn/vim-surround.git

이제 다음과 같은 subtree push 명령을 사용할 수 있습니다.

git subtree push --prefix=.vim/bundle/tpope-vim-surround/ durdn-vim-surround main
git push using: durdn-vim-surround main
Counting objects: 5, done.
Delta compression using up to 4 threads.
Compressing objects: 100% (3/3), done.
Writing objects: 100% (3/3), 308 bytes, done.
Total 3 (delta 2), reused 0 (delta 0)
To ssh://git@bitbucket.org/durdn/vim-surround.git
02199ea..dcacd4b dcacd4b21fe51c9b5824370b3b224c440b3470cb -} main

이제 준비가 되었으며 패키지 관리자에게 풀리퀘스트를 열 수 있습니다.

Git subtree 명령을 사용하지 않고 가능합니까?

예! 가능합니다. git subtree는 하위 트리 병합 전략과 다릅니다. 어떤 이유로든 git subtree를 사용할 수 없더라도 병합 전략은 계속 사용할 수 있습니다. 방법은 다음과 같습니다.

종속성을 단순한 git remote로 추가합니다.

git remote add -f tpope-vim-surround https://bitbucket.org/vim-plugins-mirror/vim-surround.git

리포지토리에 대한 종속성 콘텐츠를 읽기 전에 지금까지의 플러그인 전체 트리 기록을 추적할 수 있도록 병합을 기록해야 합니다.

git merge -s ours --no-commit tpope-vim-surround/main

다음과 같이 출력됩니다.

Automatic merge went well; stopped before committing as requested

그런 다음 플러그인 리포지토리에 있는 최신 트리 개체의 콘텐츠를 커밋할 준비가 된 작업 디렉터리로 읽어 들입니다.

git read-tree --prefix=.vim/bundle/tpope-vim-surround/ -u tpope-vim-surround/main

이제 커밋할 수 있습니다(이는 우리가 읽은 트리의 기록을 보존하는 병합 커밋이 됨).

git ci -m"[subtree] adding tpope-vim-surround"
[stree 779b094] [subtree] adding tpope-vim-surround

프로젝트를 업데이트하고 싶을 때 이제 git subtree 병합 전략을 사용하여 풀할 수 있습니다.

git pull -s subtree tpope-vim-surround main

Git subtree, 훌륭한 대안

Git 하위 모듈을 한동안 사용하고 나면 git subtree가 Git 하위 모듈의 많은 문제를 해결해 준다는 사실을 알게 될 것입니다. 항상 그렇듯이 Git에 관한 모든 것에는 기능을 최대한 활용하기 위한 학습 곡선이 있습니다.

맞춤 추천

Bitbucket 블로그

DevOps 학습 경로

Git에 대해 자세히 알아보기

이 허브에서 더 많은 Git 가이드 및 리소스를 찾아보세요.