git worktree

seunghyun·2026년 1월 2일

Version Control

목록 보기
1/1

git worktree로 여러 피처 동시에 개발하기

1. git worktree

일반적인 Git 저장소는 단 하나의 작업 디렉터리만 가진다. 브랜치를 체크아웃하면 파일들이 전부 그 브랜치의 내용으로 바뀌고, 다른 브랜치를 보려면 현재 작업을 멈추고 다시 파일을 교체해야 한다.

Git Worktree는 이 규칙을 완전히 뒤엎는다. 동일한 Git 저장소에 여러 개의 독립된 작업 디렉터리를 가질 수 있게 해준다.

도서관 비유

일반적인 GitGit Worktree
비유책상이 1개인 도서관책상이 여러 개인 도서관
브랜치 전환지금 보던 책을 덮고 → 책장에 넣고 → 새 책을 가져옴첫 번째 책상에 책을 펼쳐 두고 → 두 번째 책상으로 걸어감
차이점한 번에 하나씩만 가능동시에 여러 브랜치에서 작업 가능

모든 책상(Worktree)은 같은 도서관(.git 폴더)을 공유하지만, 물리적으로는 완전히 분리된 공간이다.

내부 구조

Worktree를 생성하면 새 폴더가 만들어지는데, 이 폴더는 원본 저장소의 .git 폴더에 연결된다. 프로젝트 전체를 또 복제하는 것이 아니라, 중앙의 두뇌 역할을 하는 .git 폴더는 공유하고, 작업할 수 있는 깨끗한 공간만 새로 내어주는 것이다.

my-project/              ← 원래 프로젝트 (메인 브랜치)
├── .git/                ← 공유되는 두뇌 (히스토리, 커밋 기록)
├── src/
└── ...

../hotfix-folder/        ← 새 Worktree (메인 브랜치 기반)
├── .git (파일)          ← 원본 .git 폴더를 가리키는 포인터
├── src/
└── ...

디스크 공간 절약: 프로젝트를 통째로 clone하는 것과 달리, .git 데이터베이스를 공유하므로 디스크 공간을 크게 절약할 수 있다.


2. 긴급 핫픽스 대응

feature/login 브랜치에서 새 기능을 개발 중인데, 즉시 버그를 수정해야 하는 상황이다.

Step 1. 현재 상태 확인

git status
# On branch feature/login
# Changes not staged for commit:
#   modified: login.js
#   modified: style.css

커밋하지 않은 수정 사항들이 있다. 이 지저분한 상태를 전혀 건드리고 싶지 않다.

Step 2. 새로운 Worktree 생성

git worktree add ../hotfix-folder main
  • 현재 폴더 바깥hotfix-folder라는 새 디렉터리를 만든다
  • 그 안에 main 브랜치를 체크아웃한다
  • 상위 폴더(../)를 사용해서 프로젝트 폴더 바깥에 만드는 것!

Step 3. 새 Worktree로 이동

cd ../hotfix-folder
ls
# → main 브랜치의 깨끗한 파일들이 그대로 보인다

원래 폴더의 지저분한 feature/login 브랜치 변경 사항들은 안전하게 그대로 남아 있다.

Step 4. 평소처럼 작업

git checkout -b hotfix/critical-bug    # 버그 수정 브랜치 생성
# ... 코드 수정 ...
git add . && git commit -m "fix: critical production bug"
git push origin hotfix/critical-bug

Worktree라고 해서 특별한 워크플로우가 있는 것이 아니다. 평소와 똑같다.

Step 5. 원래 작업으로 복귀

cd ../my-project
git status
# On branch feature/login
# Changes not staged for commit:
#   modified: login.js
#   modified: style.css

모든 것이 자리를 비우기 전과 정확히 똑같은 상태다. git stash pop 같은 복잡한 과정이 전혀 필요 없다.


3. 흔히 저지르는 3가지 실수

실수 1: Worktree를 프로젝트 폴더 안에 만드는 것

# 잘못된 방법
git worktree add ./hotfix main

# 올바른 방법
git worktree add ../hotfix main

프로젝트 폴더 안에 만들면, Git이 새 폴더를 추적되지 않는 디렉터리로 감지해서 git status가 지저분해진다. 항상 프로젝트 폴더 바깥(나란한 위치)에 만들자.

실수 2: 이미 체크아웃된 브랜치 오류

Git은 두 개의 다른 폴더가 동시에 같은 브랜치를 수정하는 위험한 상황을 막아준다.

# 메인 프로젝트에서 이미 main 브랜치를 보고 있는데
# 새 Worktree에도 main을 체크아웃하려 하면 → Fatal 오류!

# 해결책: 보기만 할 거라면 --detach 옵션 사용
git worktree add ../review-folder --detach

실수 3: 의존성 관리를 잊는 것

새 Worktree는 완전히 깨끗한 새 디렉터리다. node_modules, venv 같은 의존성 폴더를 공유하지 않는다.

cd ../hotfix-folder
npm install    # 반드시 의존성을 새로 설치해야 한다!

4. Worktree 관리하기 — 조회, 삭제, 정리

4.1 Worktree 목록 조회

git worktree list
/home/user/my-project         abc1234 [main]           ← 기본 작업 공간 (제거 불가)
/home/user/hotfix-folder      def5678 [hotfix/bug]     ← 추가 Worktree
/home/user/feature-folder     ghi9012 [feature/login]  ← 추가 Worktree

각 줄은 폴더 경로, 최신 커밋 해시, 브랜치 이름을 보여준다.

4.2 Worktree 삭제 — remove를 사용하자

# 올바른 방법 (안전 장치 포함)
git worktree remove ../hotfix-folder

# 잘못된 방법 (git이 모른다!)
rm -rf ../hotfix-folder

git worktree remove안전 장치가 있다

  • 저장하지 않은 변경 사항이 있으면 삭제를 중단한다
  • 정말 삭제하려면 --force 옵션을 사용해야 한다

중요: rm -rf로 폴더를 직접 지우면 Git은 폴더가 사라진 사실을 모른다. 이를 유령 Worktree라고 한다.

4.3 유령 Worktree 정리 — prune

폴더를 수동으로 삭제해버렸다면:

git worktree list    # 이미 삭제된 Worktree가 여전히 보인다
git worktree prune   # 유령 항목을 Git 기록에서 제거
git worktree list    # 이제 목록이 정확해진다

주의: prune을 실행하면 해당 Worktree의 메타데이터가 완전히 삭제된다. 스테이징해둔 변경 사항이 있었다면 복구 불가능하므로 실행 전에 확인하자.

4.4 Worktree 잠금 — lock

USB 드라이브나 네트워크 공유 폴더처럼 불안정한 저장소에 Worktree를 둘 때 유용하다.

git worktree lock ../usb-worktree     # 잠금: prune해도 기록 보존
git worktree unlock ../usb-worktree   # 잠금 해제

4.5 Worktree vs 브랜치 — 개념적 차이

git worktree removegit branch -D
물리적 작업 공간(폴더) 삭제브랜치 포인터 삭제
작업 기록은 .git에 안전하게 보관커밋 기록은 reflog에 남아있음

Worktree를 제거한다고 브랜치가 사라지지 않는다. 브랜치까지 삭제하고 싶다면 별도로 git branch -D 명령을 실행해야 한다.


5. 실수로 Worktree를 지웠을 때 복구 방법

상황 1: 폴더 삭제 + 복구할 것 없음 → 정리 후 재생성

git worktree prune                          # 유령 기록 정리
git worktree add ../feature-folder feature  # 같은 브랜치로 새 Worktree 생성

이것은 복구가 아니라 재생성이다. 브랜치의 커밋 기록은 유지되지만, 커밋하지 않은 변경 사항은 영구적으로 사라진다.

상황 2: 폴더 삭제 + prune 아직 미실행 + 스테이징된 변경 사항 있음 → 복구 가능

git add로 스테이징한 내용은 메인 저장소의 .git 폴더에 저장되므로, prune 전이라면 복구할 수 있다.

mkdir ../feature-folder                                   # 1. 같은 이름의 폴더 재생성
echo "gitdir: /path/to/repo/.git/worktrees/feature" > ../feature-folder/.git  # 2. 연결 파일 생성
cd ../feature-folder
git status                                                # 3. 스테이징된 변경 사항 확인
git checkout -- .                                         # 4. 파일 복구

주의: 이 방법은 prune을 실행하기 전에만 가능하다!

상황 3: 브랜치까지 삭제됨 → reflog으로 복구

git reflog                              # 삭제된 브랜치의 마지막 커밋 해시 찾기
git branch feature/recovered abc1234    # 해당 해시로 브랜치 재생성

reflog은 Git이 모든 HEAD 이동 기록을 보관하는 블랙박스다.

상황 4: Worktree 폴더를 이동함 → repair

# 이동한 Worktree 폴더 안에서 실행
cd ../moved-folder
git worktree repair

# 또는 메인 저장소에서 새 경로 지정
git worktree repair ../moved-folder

6. Bare Repository 전략

시니어 개발자의 프로젝트 폴더를 열어보면 이런 구조를 볼 수 있다

my-project/
├── .bare/          ← 순수한 Git 데이터베이스 (두뇌)
├── main/           ← main 브랜치 Worktree (몸)
├── staging/        ← staging 브랜치 Worktree
└── feature-x/     ← feature 브랜치 Worktree

더 이상 지저분한 git stash도 없고, 작업을 바꿀 때마다 npm install을 기다릴 필요도 없고, "지금 어느 브랜치에 있지?"라고 당황할 일도 없다.

Bare Repository 설정 방법

# 1. 루트 폴더 생성 및 이동
mkdir my-project && cd my-project

# 2. Bare 레포지토리로 clone (작업 파일 없이 Git DB만 다운로드)
git clone --bare <repo-url> .bare

# 3. 첫 번째 Worktree 생성
git --git-dir=.bare worktree add main main
  • .bare 폴더: 순수한 Git 데이터베이스 (두뇌)
  • main 폴더: 실제 코드를 담는 작업 공간 (몸)
  • 루트 디렉터리는 완벽하게 정돈된 상태 유지

참고: 상대 경로 기능은 Git 2.48 이상에서 공식 지원된다. 이전 버전에서는 폴더 이동 시 Worktree 연결이 끊어질 수 있다.

Bare Repository에서의 명령어 실행

# 방법 1: -C 플래그 사용 (권장)
git -C .bare branch -a                    # 전체 브랜치 목록
git --git-dir=.bare worktree add feature feature/new-feature

# 방법 2: Worktree 폴더 안에서 직접 실행
cd main
git branch -a                              # 평소처럼 사용 가능

절대 하면 안 되는 것

# Bare 레포지토리 루트에서 git pull 실행 금지!
cd my-project
git -C .bare pull    # 에러 발생! Bare 폴더는 코드를 담을 '몸'이 없다

# 올바른 방법
git -C .bare fetch   # 1. 데이터베이스만 안전하게 업데이트
cd main
git pull             # 2. 실제 Worktree 안에서 pull

7. PR 리뷰 샌드박스 만들기

동료가 PR #42를 올렸다고 하자. 기존 워크플로우는 고통스럽다

내 작업 stash → 브랜치 전환 → 의존성 재설치 → 테스트 → 다시 원래 작업으로 복귀...

Worktree를 사용하면 일회용 리뷰 환경을 만들 수 있다

# 1. PR 브랜치 가져오기
git fetch origin pull/42/head:pr-42

# 2. 리뷰용 Worktree 생성
git worktree add ../review-pr42 pr-42

# 3. 격리된 환경에서 마음껏 테스트
cd ../review-pr42
npm install
npm test
# 코드를 망가뜨려도 OK! 원래 작업에는 영향 없음

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

: 터미널을 여러 개 띄워서 여러 PR을 동시에 리뷰할 수도 있다!

월요일 아침 시나리오..

세 가지 일이 동시에 주어졌다
1. 기능 X 계속 개발
2. 동료의 PR #55 리뷰
3. 운영 서버 긴급 버그 수정

터미널 1: ~/my-project/feature-x/   → localhost:3000  (기능 개발)
터미널 2: ~/my-project/review-pr55/ → localhost:3001  (PR 리뷰)
터미널 3: ~/my-project/hotfix/      → localhost:3002  (긴급 버그 수정)

세 가지 버전의 앱이 동시에 돌아간다. Stash도, 충돌도, 스트레스도 없다.

단, 포트 번호는 자동으로 바뀌지 않으므로 각 프로젝트의 설정에서 수동으로 지정해야 한다.


8. 비용과 최적화

디스크 & 시간 비용

항목비용
node_modules 평균 용량~450MB
Worktree 3개의 의존성~1.35GB
npm install 소요 시간 (대형 프로젝트)~5분/회
Worktree 3개 설치 시간~15분

최적화 방법

  1. pnpm 사용: 파일을 매번 복사하는 대신 중앙 저장소의 파일에 링크를 걸어 디스크 사용량과 설치 시간 모두 절감
  2. 즉시 정리 습관: 리뷰가 끝나면 바로 git worktree remove로 삭제
  3. 적합한 프로젝트에 사용: 장기적인 피처 브랜치가 많은 대형 프로젝트에 가장 효과적

9. 주요 명령어 치트시트

명령어설명
git worktree add ../폴더 브랜치새 Worktree 생성
git worktree list열린 모든 Worktree 목록 조회
git worktree remove ../폴더Worktree 안전하게 삭제
git worktree prune유령 Worktree 기록 정리
git worktree lock ../폴더Worktree 잠금 (prune 보호)
git worktree unlock ../폴더Worktree 잠금 해제
git worktree repair이동/손상된 Worktree 복구

마무리 및 요약

  1. 여러 브랜치를 각기 다른 폴더에서 동시에 체크아웃할 수 있다
  2. 하나의 Git 히스토리를 공유하므로 git clone보다 디스크 공간을 훨씬 절약한다
  3. 피처 개발 + 긴급 버그 수정 + 코드 리뷰를 동시에 하는 멀티태스킹에 완벽하다

0개의 댓글