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

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

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

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. 참고 자료