요약. 브랜치를 옮길 때마다 git stash 를 하고, 돌아와서 빌드를 처음부터 다시 돌리고 있다면 이 글이 그 낭비를 없앱니다. worktree 는 브랜치 전환을 폴더 이동으로 바꿉니다. 시작에 필요한 명령은 세 개고, 미리 알아야 할 함정도 세 개입니다.
전환 비용은 소스가 아니라 빌드 산출물에 있습니다
git switch 가 갈아끼우는 것은 추적 파일뿐입니다. 정작 비싼 것은 그 옆에 남는 obj/, bin/, node_modules/ 입니다. 소스가 통째로 바뀌면 증분 빌드가 무효화되므로, 한 줄 확인하러 브랜치를 옮겼다가 몇 분을 기다립니다. 작업 중이던 변경은 stash 로 밀어 넣어야 하고, 돌아와 pop 하다 충돌을 만납니다.
저장소를 하나 더 clone 하면 해결되지만 히스토리와 오브젝트가 그대로 복제됩니다. worktree 는 저장소 하나에 작업 폴더만 여러 개 붙입니다. 오브젝트와 refs 는 공유하고 체크아웃만 분리하는 구조입니다. 2015년 7월 29일 Git 2.5 에 add/list/prune 로 들어온 기본 기능이라 따로 설치할 것도 없습니다.
| 방식 | 히스토리 | 빌드 캐시 | 동시 작업 |
|---|---|---|---|
| stash + switch | 하나 | 전환마다 무효화 | 불가 |
| 저장소 추가 clone | 폴더마다 복제 | 유지 | 가능 |
| worktree | 공유 | 유지 | 가능 |
clone 을 늘리면 fetch 도 폴더마다 따로 돌려야 하고, 한쪽에서 만든 브랜치가 다른 쪽에 보이지 않습니다. worktree 는 refs 를 공유하므로 옆 폴더에서 방금 만든 브랜치가 그 자리에서 보입니다.
명령 세 개로 시작합니다
git worktree add ../hotfix -b hotfix # 새 브랜치 + 폴더를 한 번에
git worktree list # 어느 폴더에 어느 브랜치가 붙었는지
git worktree remove ../hotfix # 폴더 정리 (브랜치는 남습니다)
첫 줄은 형제 폴더 ../hotfix 를 만들고 거기에 새 브랜치를 체크아웃합니다. 원래 폴더는 손대지 않으므로 빌드 산출물도, 편집 중이던 파일도 그대로입니다. 이미 있는 브랜치를 꺼내려면 -b 를 빼고 git worktree add ../review feature/login 으로 씁니다. list 는 폴더마다 한 줄씩 sha 와 브랜치를 찍습니다.
.../demo dfd2991 [main]
.../hotfix dfd2991 [hotfix]
함정은 셋뿐입니다
- 같은 브랜치를 두 폴더에 둘 수 없습니다. 이미 붙은 브랜치를 또 체크아웃하면
fatal: 'main' is already used by worktree at ...로 거부합니다. 브랜치와 폴더는 일대일입니다. remove는 폴더만 지웁니다. 브랜치는 그대로 남으니git branch -d로 따로 지웁니다. 반대로 탐색기에서 폴더를 지웠으면 등록 정보가 남으므로git worktree prune으로 정리합니다.- 링크된 worktree 의
.git은 폴더가 아니라 파일입니다. 안에는gitdir: .../worktrees/hotfix한 줄이 들어 있습니다..git디렉터리 존재를 가정하고 경로를 조립하는 스크립트나 툴은 여기서 깨집니다.
메인 폴더의 특권을 없애는 bare 레이아웃
기본 사용법은 "메인 저장소 + 딸린 폴더" 라서 메인이 특별한 지위를 갖습니다. 메인을 지우면 나머지가 고아가 되고, 폴더 목록에서 어느 것이 원본인지 기억해야 합니다. 폴더를 전부 대등하게 두려면 bare 저장소를 숨기고 브랜치마다 폴더를 하나씩 두는 배치가 낫습니다.
proj/
.bare/ # bare 저장소 (여기엔 작업 파일이 없습니다)
.git # "gitdir: ./.bare" 한 줄이 든 파일
master/ # 폴더 = 브랜치
feature-login/
git clone --bare <url> .bare 로 받고, .git 포인터 파일을 만든 뒤 git worktree add master 로 첫 폴더를 냅니다. 이후 브랜치 이름과 폴더 이름이 일대일이라 ls 만으로 지금 벌여 놓은 작업이 전부 보입니다.
정리
브랜치 전환의 실제 비용은 소스 교체가 아니라 빌드 산출물 무효화입니다. worktree 는 폴더를 분리해 그 비용을 0으로 만들고, add/list/remove 세 명령이면 충분합니다. 브랜치와 폴더가 일대일이라는 제약, 그리고 .git 이 파일이라는 사실만 기억하면 사고가 없습니다.
지금 저장소에서 git worktree add ../hotfix -b hotfix 를 한 번 실행해 보십시오. 다음 편에서는 이렇게 벌려 놓은 폴더를 병렬 작업 슬롯으로 쓰고, 마지막에 한 줄로 병합하는 방법을 다룹니다.
