Git Worktree 완벽 가이드: 생성부터 정리까지 실전 워크플로우

하나의 레포에서 여러 브랜치를 동시에 작업하고 싶다면? Git Worktree로 stash 없이 브랜치 전환하고, PR 리뷰도 깔끔하게 처리하세요.

1. 문제 상황

익숙한 시나리오

개발하다 보면 이런 상황을 자주 만납니다:

현재 상황: feature/new-dashboard 브랜치에서 대규모 리팩토링 중
갑자기: 프로덕션 버그 발생! main 브랜치에서 핫픽스 필요
문제: 작업 중인 변경사항이 수십 개 파일에 걸쳐 있음

기존 방식의 한계:

# 방법 1: stash 사용 - 복잡하고 위험
git stash push -m "WIP: dashboard refactoring"
git checkout main
# ... 핫픽스 작업 ...
git checkout feature/new-dashboard
git stash pop  # ← 충돌 발생 가능!

# 방법 2: 커밋하기 - 지저분한 히스토리
git add .
git commit -m "WIP: incomplete work"  # ← 나쁜 커밋 메시지
git checkout main
# ... 핫픽스 작업 ...
git checkout feature/new-dashboard
# 나중에 rebase로 정리해야 함

실제 발생하는 문제들

방식 문제점
git stash stash 충돌, 잊어버림, 복잡한 stash 목록
WIP 커밋 지저분한 히스토리, rebase 필요
레포 복제 디스크 낭비, 설정 중복, 동기화 문제
# 레포 복제 방식의 문제
git clone repo ~/project-main
git clone repo ~/project-feature  # ← 전체 히스토리 중복!

# 디스크 사용량 확인
du -sh ~/project-main/.git    # 500MB
du -sh ~/project-feature/.git # 500MB  ← 똑같이 500MB 낭비

2. Git Worktree란?

핵심 개념

Git Worktree는 하나의 .git 디렉토리를 공유하면서 여러 작업 디렉토리를 만드는 기능입니다.

# 기존 방식: 레포 복제
~/project-main/.git      (500MB)
~/project-feature/.git   (500MB)
총 1GB

# Worktree 방식: .git 공유
~/project/.git           (500MB) ← 하나만!
~/project-feature/       (소스 파일만, 수 MB)
총 ~500MB

작동 원리

┌─────────────────────────────────────────────────────┐
│                    .git 디렉토리                      │
│  (커밋 히스토리, 객체, 설정 - 모든 worktree가 공유)      │
└─────────────────────────────────────────────────────┘
         │                           │
         ▼                           ▼
┌─────────────────┐         ┌─────────────────┐
│   Main Worktree │         │ Linked Worktree │
│   ~/project     │         │ ~/project-feat  │
│   (main branch) │         │ (feature branch)│
│                 │         │                 │
│   src/          │         │   src/          │
│   package.json  │         │   package.json  │
│   ...           │         │   ...           │
└─────────────────┘         └─────────────────┘

Worktree의 장점

# 1. 디스크 효율성
# .git 히스토리를 공유하므로 추가 용량이 거의 없음

# 2. 즉시 전환
# checkout 없이 다른 디렉토리로 이동만 하면 됨
cd ~/project-feature  # ← 끝!

# 3. 동시 작업
# IDE 창 2개로 두 브랜치를 동시에 열어둘 수 있음

# 4. 빌드 캐시 유지
# 각 worktree가 독립된 node_modules, build 캐시 보유
~/project/node_modules        # main용
~/project-feature/node_modules # feature용

3. Worktree 생성하기

기본 생성 명령어

# 기본 문법
git worktree add <경로> <브랜치>

# 예시: 기존 브랜치로 worktree 생성
git worktree add ../project-feature feature/new-dashboard
#                 └─ 새 디렉토리      └─ 기존 브랜치

# 예시: 새 브랜치 생성과 동시에 worktree 생성
git worktree add -b hotfix/urgent-fix ../project-hotfix main
#                └─ 새 브랜치 생성     └─ 경로           └─ 기반 브랜치

실전 예시: PR 리뷰용 worktree

# 시나리오: PR #42를 로컬에서 테스트하고 싶음

# 1. 원격 브랜치 fetch
git fetch origin pull/42/head:pr-42

# 2. PR용 worktree 생성
git worktree add ../project-pr-42 pr-42

# 3. 해당 디렉토리에서 테스트
cd ../project-pr-42
npm install
npm test

# 4. 리뷰 완료 후 정리
cd ../project
git worktree remove ../project-pr-42
git branch -D pr-42

실전 예시: feature 브랜치 개발

# 현재 위치: ~/projects/my-app (main 브랜치)

# 1. feature 브랜치용 worktree 생성
git worktree add -b feat/check-usage ../my-app-check-usage main

# 결과:
# ~/projects/my-app              ← main 브랜치 (기존)
# ~/projects/my-app-check-usage  ← feat/check-usage 브랜치 (새로 생성)

# 2. feature 작업 시작
cd ../my-app-check-usage
code .  # VS Code로 열기

# 3. 동시에 main에서 다른 작업 가능
cd ../my-app
# main 브랜치 작업...

네이밍 컨벤션

# 권장: 프로젝트명-브랜치설명
git worktree add ../my-app-feature-auth feat/auth
git worktree add ../my-app-hotfix-login hotfix/login
git worktree add ../my-app-pr-42 pr-42

# 또는: 프로젝트명-브랜치타입
git worktree add ../my-app-feat feat/new-feature
git worktree add ../my-app-fix hotfix/urgent

# 피해야 할 것
git worktree add ../temp feature  # ← 모호함
git worktree add ../work feat     # ← 구분 안됨

4. Worktree 관리하기

현재 worktree 목록 확인

git worktree list

출력 예시:

/Users/kim/projects/my-app              abc1234 [main]
/Users/kim/projects/my-app-check-usage  def5678 [feat/check-usage]
/Users/kim/projects/my-app-pr-42        ghi9012 [pr-42]

상세 정보 확인

git worktree list --porcelain

출력 예시:

worktree /Users/kim/projects/my-app
HEAD abc1234567890
branch refs/heads/main

worktree /Users/kim/projects/my-app-check-usage
HEAD def5678901234
branch refs/heads/feat/check-usage

Worktree 간 이동

# 단순히 디렉토리 이동
cd ../my-app-check-usage

# 또는 절대 경로
cd /Users/kim/projects/my-app-check-usage

# 팁: 자주 쓰는 worktree는 alias 설정
echo 'alias cdmain="cd ~/projects/my-app"' >> ~/.zshrc
echo 'alias cdfeat="cd ~/projects/my-app-check-usage"' >> ~/.zshrc

Worktree에서 브랜치 작업

# 각 worktree에서 평소처럼 git 명령어 사용
cd ../my-app-check-usage

git add .
git commit -m "feat: add new feature"
git push origin feat/check-usage

# 주의: 같은 브랜치를 두 worktree에서 동시에 checkout 불가!
git checkout main  # ← 에러! main은 다른 worktree에서 사용 중

5. Worktree 정리하기

작업 완료 후 정리 프로세스

PR이 머지된 후의 전체 정리 플로우:

# 1. 메인 worktree에서 머지된 내용 pull
cd ~/projects/my-app
git pull origin main

# 2. worktree 제거
git worktree remove ../my-app-check-usage
# 또는 강제 제거 (uncommitted changes가 있을 때)
git worktree remove --force ../my-app-check-usage

# 3. 로컬 브랜치 삭제
git branch -d feat/check-usage
# 또는 강제 삭제 (머지되지 않은 브랜치)
git branch -D feat/check-usage

# 4. 원격 브랜치 삭제 (필요시)
git push origin --delete feat/check-usage

수동 삭제 후 정리

디렉토리를 직접 삭제한 경우:

# worktree 디렉토리 수동 삭제
rm -rf ../my-app-check-usage

# dangling worktree 참조 정리
git worktree prune

# 정리 확인
git worktree list

일괄 정리 스크립트

#!/bin/bash
# cleanup-worktrees.sh

# 머지된 브랜치의 worktree 정리
for worktree in $(git worktree list --porcelain | grep "^worktree" | cut -d' ' -f2); do
    branch=$(git -C "$worktree" branch --show-current)

    # main worktree는 스킵
    if [ "$branch" = "main" ] || [ "$branch" = "master" ]; then
        continue
    fi

    # 머지 여부 확인
    if git branch --merged main | grep -q "$branch"; then
        echo "Removing merged worktree: $worktree ($branch)"
        git worktree remove "$worktree"
        git branch -d "$branch"
    fi
done

gone 브랜치 정리

원격에서 삭제된 브랜치(gone)와 연결된 worktree 정리:

# 원격 브랜치 정보 업데이트
git fetch --prune

# gone 상태인 브랜치 확인
git branch -vv | grep ': gone]'

# gone 브랜치들의 worktree 정리
git branch -vv | grep ': gone]' | awk '{print $1}' | while read branch; do
    worktree=$(git worktree list | grep "\[$branch\]" | awk '{print $1}')
    if [ -n "$worktree" ]; then
        echo "Removing worktree for gone branch: $worktree"
        git worktree remove "$worktree" 2>/dev/null || rm -rf "$worktree"
    fi
    git branch -D "$branch"
done

git worktree prune

6. 핵심 개념 정리

명령어 요약

명령어 설명 예시
git worktree add <path> <branch> 기존 브랜치로 worktree 생성 git worktree add ../proj-feat feature
git worktree add -b <new-branch> <path> <base> 새 브랜치 생성 + worktree git worktree add -b fix ../proj-fix main
git worktree list 모든 worktree 목록 -
git worktree remove <path> worktree 제거 git worktree remove ../proj-feat
git worktree prune 삭제된 worktree 참조 정리 -
git worktree move <path> <new-path> worktree 이동 git worktree move ../old ../new
git worktree lock <path> worktree 잠금 (prune 방지) git worktree lock ../important
git worktree unlock <path> worktree 잠금 해제 git worktree unlock ../important

Worktree vs 다른 방식 비교

방식 디스크 전환 속도 동시 작업 복잡도
git stash 0 느림 중간
git checkout 0 느림 낮음
레포 복제 높음 빠름 낮음
Worktree 낮음 빠름 중간

Worktree 제한사항

# 1. 같은 브랜치를 여러 worktree에서 checkout 불가
git worktree add ../another-main main
# error: 'main' is already checked out at '/Users/kim/projects/my-app'

# 해결: 다른 브랜치 사용 또는 detached HEAD
git worktree add --detach ../temp-main main

# 2. bare repository에서는 main worktree가 없음
git clone --bare repo.git
cd repo.git
git worktree add ../working main  # ← 모든 작업을 worktree로

# 3. worktree 내에서 worktree 생성은 가능하지만 권장하지 않음
cd ../my-app-check-usage
git worktree add ../my-app-sub-feature  # 가능하지만 혼란스러움

7. 베스트 프랙티스

Worktree 사용 체크리스트

✅ Worktree 생성 전
- [ ] 명확한 디렉토리 네이밍 규칙 정하기
- [ ] 프로젝트별 worktree 위치 통일 (예: 같은 부모 디렉토리)
- [ ] IDE 설정이 worktree별로 독립적인지 확인

✅ 작업 중
- [ ] 각 worktree에서 독립적으로 의존성 설치
- [ ] worktree 간 파일 복사 시 git 상태 확인
- [ ] 정기적으로 `git worktree list`로 현황 파악

✅ 정리 시
- [ ] PR 머지 후 즉시 worktree 정리
- [ ] 로컬/원격 브랜치 함께 삭제
- [ ] `git worktree prune`으로 찌꺼기 정리

IDE 설정 팁

# VS Code: 각 worktree를 별도 창으로
code ~/projects/my-app
code ~/projects/my-app-check-usage

# VS Code workspace로 관리
cat > ~/projects/my-app.code-workspace << 'EOF'
{
  "folders": [
    { "path": "my-app", "name": "main" },
    { "path": "my-app-check-usage", "name": "feature" }
  ]
}
EOF
code ~/projects/my-app.code-workspace

Git alias 설정

# ~/.gitconfig에 추가
git config --global alias.wt 'worktree'
git config --global alias.wtl 'worktree list'
git config --global alias.wta 'worktree add'
git config --global alias.wtr 'worktree remove'

# 사용 예시
git wt list
git wta ../my-app-feat feat/new
git wtr ../my-app-feat

자동 정리 Git Hook

# .git/hooks/post-merge (PR 머지 후 자동 실행)
#!/bin/bash

# 머지된 브랜치 정리 알림
merged_branches=$(git branch --merged main | grep -v "^\*\|main\|master")

if [ -n "$merged_branches" ]; then
    echo "🧹 다음 브랜치들이 머지되었습니다. 정리하세요:"
    echo "$merged_branches"
    echo ""
    echo "정리 명령어:"
    echo "git worktree list"
    echo "git worktree remove <path>"
    echo "git branch -d <branch>"
fi

8. FAQ

Q: Worktree와 submodule의 차이점은?

A: 완전히 다른 기능입니다.

# Worktree: 같은 레포의 다른 브랜치를 동시에 작업
git worktree add ../feature feat/new  # 같은 레포!

# Submodule: 다른 레포를 현재 레포에 포함
git submodule add https://github.com/other/repo  # 다른 레포!

Q: Worktree에서 npm install을 따로 해야 하나요?

A: 네, 각 worktree는 독립된 작업 디렉토리이므로 node_modules도 별도입니다.

cd ../my-app-check-usage
npm install  # ← 필수!

# 장점: 브랜치별로 다른 의존성 버전 테스트 가능
# 단점: 디스크 사용량 증가, 설치 시간

Q: Worktree 디렉토리를 실수로 삭제했어요

A: git worktree prune으로 정리하면 됩니다.

# 삭제된 worktree 참조 정리
git worktree prune

# 확인
git worktree list

# 필요하면 다시 생성
git worktree add ../my-app-check-usage feat/check-usage

Q: 두 worktree에서 같은 파일을 수정하면 어떻게 되나요?

A: 각각 독립된 작업 디렉토리이므로 충돌 없이 수정 가능합니다. 단, 나중에 브랜치를 머지할 때 일반적인 merge conflict가 발생할 수 있습니다.

# worktree A (main)
echo "version A" > file.txt
git commit -am "Update from main"

# worktree B (feature)
echo "version B" > file.txt
git commit -am "Update from feature"

# 머지 시 충돌 발생 - 일반적인 git 워크플로우와 동일
git merge feature
# CONFLICT!

Q: Worktree를 다른 컴퓨터로 옮길 수 있나요?

A: Worktree는 절대 경로로 연결되어 있어서 직접 복사하면 안 됩니다. 다른 컴퓨터에서는 새로 생성하세요.

# ❌ 잘못된 방법
scp -r ../my-app-check-usage remote:/projects/

# ✅ 올바른 방법 (원격에서)
git worktree add ../my-app-check-usage feat/check-usage

9. 참고 자료