이번 주 TSBM 모임에 갔다가 흥미로운 이야기를 들었습니다.
옆에 계신 개발자분과 이야기하면서 생산성을 위한 앱이나 도구에 대한 이야기가 나왔고, 그 중 하나가 git worktree였습니다.
worktree를 쓰게 되면, 브랜치별로 작업하는게 훨씬 편하다고 하셨고, 저는 처음 들어본 내용이어서 되물어봤습니다.
git stash로 할 수 있는 거 아닌가요?
그분이 웃으시면서 이렇게 말씀하셨습니다.
"저는 worktree 씁니다. stash보다 훨씬 편해요. 한번 써보세요!"
Worktree?
Git을 나름 잘 쓰고 있다고 생각했는데 5년 넘게 써왔는데 처음 듣는 단어였습니다. 부끄럽기도 하고, 호기심이 생겨서 바로 찾아보았습니다.
그동안 git stash로도 문제를 해결할 수 있었다고 생각했는데, 다시 생각해보니 그건 비효율적으로 작업하고 있었던것 임을 알게 되었습니다.
간단하게 말하면, 하나의 Git 저장소를 여러 디렉토리에서 동시에 작업할 수 있게 해주는 기능입니다.
일반적으로 Git 저장소는 이렇게 생겼습니다.
my-project/
├── .git/
├── src/
└── README.md
한 번에 하나의 브랜치만 체크아웃할 수 있습니다.
하지만 worktree를 사용하면,
my-project/ # main 브랜치
├── .git/
├── src/
└── README.md
my-project-feature-a/ # feature-a 브랜치
├── src/
└── README.md
my-project-hotfix/ # hotfix 브랜치
├── src/
└── README.md
이렇게 동일한 저장소의 여러 브랜치를 각각 다른 디렉토리에서 동시에 작업할 수 있습니다.
각 디렉토리는 독립적인 작업 공간이지만, .git 디렉토리는 공유합니다. 그래서 commit, push, pull 같은 작업은 모두 동기화됩니다.
내가 그동안 겪었던 전형적인 시나리오는 이랬다.
상황:
feature/user-dashboard 브랜치에서 신규 기능 개발 중v1.2.3 태그에서 hotfix 필요기존 방식 (stash 사용):
# 1. 현재 작업 임시 저장
git stash save "WIP: user dashboard"
# 2. hotfix 브랜치로 이동
git checkout v1.2.3
git checkout -b hotfix/urgent-bug
# 3. 버그 수정 후 커밋
# ... 수정 작업 ...
git add .
git commit -m "Fix urgent bug"
# 4. 다시 원래 브랜치로 돌아가기
git checkout feature/user-dashboard
# 5. stash 복원
git stash pop
문제점
작업 상태를 완전히 잃어버림
동시 작업이 불가능
stash stack 관리의 어려움
git stash list
# stash@{0}: WIP: user dashboard
# stash@{1}: WIP: some old work
# stash@{2}: WIP: another feature
git stash pop을 잘못된 브랜치에서 실행하면 conflict 지옥같은 상황, Worktree 사용
# 1. hotfix용 worktree 생성
git worktree add ../my-project-hotfix v1.2.3 -b hotfix/urgent-bug
# 2. 새 터미널 열어서 hotfix 디렉토리로 이동
cd ../my-project-hotfix
# 3. 버그 수정 후 커밋
# ... 수정 작업 ...
git add .
git commit -m "Fix urgent bug"
# 4. 원래 터미널은 그대로!
# feature/user-dashboard에서 계속 작업 가능
장점
원래 작업 환경이 그대로 유지됨
동시 작업 가능
브랜치 비교가 쉬움
# 두 디렉토리를 직접 비교
diff -r my-project/src my-project-hotfix/src
# 또는 IDE에서 폴더 비교 기능 사용
Context Switching 비용 없음
더 구체적인 예시를 들어보겠습니다. 실무에서 자주 발생하는 상황입니다.
배경
v1.2.3feature/new-dashboard (v2.0.0 기능)v1.2.3에서 치명적인 버그 발견# 1. 현재 작업 중단하고 저장
git stash save "WIP: new dashboard - half done with chart component"
# 2. v1.2.3 태그로 이동
git checkout v1.2.3
# ⚠️ 여기서 모든 파일이 v1.2.3 상태로 변경됨
# ⚠️ node_modules도 다시 설치해야 할 수 있음
# 3. hotfix 브랜치 생성
git checkout -b hotfix/v1.2.3-critical-bug
# 4. 버그 수정
vim src/api/auth.js # v1.2.3 코드 구조
npm install # v1.2.3 의존성
npm test # v1.2.3 환경에서 테스트
# 5. 커밋 및 푸시
git add .
git commit -m "Fix critical auth bug in v1.2.3"
git push origin hotfix/v1.2.3-critical-bug
# 6. 다시 feature 브랜치로 복귀
git checkout feature/new-dashboard
# ⚠️ 다시 모든 파일이 변경됨
# ⚠️ node_modules 다시 설치
# 7. stash 복원
git stash pop
# ⚠️ 만약 package.json이 달라졌다면?
# ⚠️ conflict 발생 가능성
소요 시간: 약 5-10분 (의존성 재설치 포함 시 더 길어짐)
문제점
node_modules, build 디렉토리 등도 변경됨# 1. hotfix용 worktree 생성 (원래 디렉토리 그대로 유지)
git worktree add ../my-project-v1.2.3-hotfix v1.2.3 -b hotfix/v1.2.3-critical-bug
# ✅ 현재 디렉토리는 전혀 변경 없음
# ✅ feature/new-dashboard 작업 환경 그대로
# 2. 새 터미널 또는 VSCode 창에서 hotfix 디렉토리로 이동
cd ../my-project-v1.2.3-hotfix
# 3. 버그 수정 (독립적인 환경)
npm install # v1.2.3 전용 node_modules
vim src/api/auth.js # v1.2.3 코드
npm test # v1.2.3 환경에서 테스트
# 4. 커밋 및 푸시
git add .
git commit -m "Fix critical auth bug in v1.2.3"
git push origin hotfix/v1.2.3-critical-bug
# 5. 원래 디렉토리로 돌아가기
cd ../my-project
# ✅ feature/new-dashboard 환경 그대로 유지됨
# ✅ 실행 중이던 dev server도 그대로
# ✅ IDE에서 열어둔 파일도 그대로
# 6. hotfix worktree 정리 (선택사항)
git worktree remove ../my-project-v1.2.3-hotfix
소요 시간: 약 1-2분
장점:
# 기본 사용법
git worktree add <path> <branch>
# 새 브랜치 생성하면서 worktree 추가
git worktree add ../my-project-feature feature/new-feature
# 기존 브랜치로 worktree 추가
git worktree add ../my-project-main main
# 특정 커밋/태그로 worktree 추가
git worktree add ../my-project-hotfix v1.2.3 -b hotfix/bug-fix
git worktree list
# 출력 예시:
# /Users/me/my-project abc123 [main]
# /Users/me/my-project-feature def456 [feature/new-feature]
# /Users/me/my-project-hotfix ghi789 [hotfix/bug-fix]
# worktree 제거 (브랜치는 유지)
git worktree remove ../my-project-hotfix
# 또는 디렉토리를 먼저 삭제한 경우
git worktree prune
# 특정 worktree 정보
git worktree list --porcelain
| 항목 | Stash | Worktree |
|---|---|---|
| Context Switching | 브랜치 전환 시 파일 변경 | 디렉토리 이동만 |
| IDE 리인덱싱 | 매번 발생 | 없음 |
| 동시 작업 | 불가능 | 가능 |
| 작업 환경 유지 | 손실됨 | 완전 보존 |
| 코드 비교 | diff 명령어만 | 폴더 비교, 2개 IDE 창 |
| 의존성 관리 | 공유 (충돌 가능) | 독립적 |
| 디스크 사용량 | 적음 | 많음 (각 worktree마다 복사) |
| 학습 곡선 | 낮음 | 중간 |
| 사용 시나리오 | 간단한 임시 저장 | 복잡한 멀티태스킹 |
사실 저도 예전엔 이렇게 했습니다...
git clone https://github.com/user/my-project.git my-project
git clone https://github.com/user/my-project.git my-project-hotfix
언뜻 worktree와 비슷해 보인다. 하지만 결정적인 차이 3가지가 있습니다.
1. 디스크 공간
Clone은 .git 디렉토리를 매번 복사합니다. 저장소가 1GB면 3개 clone = 3GB.
Worktree는 .git을 공유합니다. 저장소가 1GB면 worktree 10개 만들어도 ~1.1GB.
2. fetch/pull 동기화
Clone은 각 디렉토리마다 따로 git fetch 해야 합니다.
Worktree는 한 곳에서 fetch하면 모든 worktree가 자동 동기화가 됩니다.
3. 브랜치 안전장치
Clone은 실수로 같은 브랜치를 여러 곳에서 체크아웃할 수 있습니다.
Worktree는 같은 브랜치를 동시에 체크아웃할 수 없습니다. 이로 인해 혹시 모를 실수를 방지할 수 있습니다.
비교표:
| 항목 | Git Clone | Git Worktree |
|---|---|---|
| 디스크 공간 | 저장소 크기 × N | 저장소 크기 × 1 |
| fetch/pull | 각각 따로 | 한 번에 모두 동기화 |
| 브랜치 중복 | 가능 (위험) | 불가능 (안전) |
같은 프로젝트에서 브랜치만 바꿔가며 작업한다면 Worktree가 압도적으로 효율적입니다.
TSBM 모임에서 우연히 들은 worktree 이야기는 제 작업 방식을 완전히 바꿔놓았습니다.
이전에는 "Git을 충분히 잘 안다"고 생각했는데, worktree는 5년 넘게 써온 나도 몰랐던 기능이었습니다. 부끄럽기도 했지만, 동시에 즐거웠습니다.
개발자로서 가장 즐거운 순간은 이런 게 아닐까.
다른 개발자들과 이야기하면서, "아 이런 방법도 있구나!" 하고 배우는 것. 그리고 그걸 바로 적용해서 생산성이 올라가는 걸 체감하는 것.
Worktree는 특히 이런 상황에서 빛을 발하는 것 같습니다.
물론 단점도 있긴 합니다. 디스크 공간을 더 많이 쓰고, 처음엔 개념이 좀 헷갈릴 수 있다. 하지만 한번 익숙해지면 돌아갈 수 없습니다.
브랜치 전환에 1분이라도 아까운 당신,
stash stack 관리에 지친 당신,
한번 worktree를 써보시면, 분명히 생산성이 올라갈 것이라고 생각합니다. :)
저도 개발팀 내부에서 worktree에 대해서 공유하고, 사용해보려고 합니다.