git worktree 는 설명으로 이해하는 것보다, “언제 어떤 명령을 치면 어떤 상황이 풀리는가” 로 익히는 편이 훨씬 빠릅니다. 실제로 이 기능이 가장 빛나는 순간은 새 기능 개발을 분리할 때, 작업 도중 긴급 hotfix가 들어왔을 때, 또는 여러 에이전트와 병렬로 브랜치를 나눠 작업할 때입니다.
이 글은 개념 설명을 최소화하고, 바로 써먹을 수 있는 예제 중심 으로 다시 정리했습니다. Git 공식 문서의 대표 예제와 KKamJi 글의 멀티 에이전트 운영 관점을 합쳐서, “어떤 명령을 언제 쓰는가”, “왜 그 예제가 유용한가”, “어디서 자주 헷갈리는가” 를 한 흐름으로 설명합니다.
Sources
- https://kkamji.net/posts/git-worktree/
- Git Docs - git-worktree
- GitHub Blog - Highlights from Git 2.42
1) 가장 기본적인 예제: 새 기능 작업을 현재 작업과 분리하기
가장 먼저 익혀야 할 예제는 “새 기능 브랜치를 별도 폴더에서 시작하는 경우” 입니다. Git 공식 문서는 가장 단순한 형태로 git worktree add ../hotfix 같은 예를 보여 주고, 이 경우 경로의 마지막 이름을 따서 새 브랜치를 만들 수 있다고 설명합니다. 실무에서는 브랜치 이름과 시작점을 명시하는 쪽이 더 읽기 쉽습니다.
# 현재 저장소에서 새 기능 작업을 별도 디렉터리로 분리
git worktree add ../feat-login -b feat/login main
# 생성된 작업공간으로 이동
cd ../feat-login
# 현재 브랜치 확인
git branch --show-current
이 명령이 하는 일은 세 가지입니다. 첫째, feat/login 이라는 로컬 브랜치를 만듭니다. 둘째, 그 브랜치를 ../feat-login 디렉터리에 체크아웃합니다. 셋째, 원래 작업 디렉터리는 그대로 두고 새 작업만 다른 폴더에서 시작하게 해 줍니다. 즉 “지금 작업 중인 변경사항을 건드리지 않고 다른 브랜치 일을 시작하고 싶다” 는 상황에서 가장 자연스럽게 쓰는 패턴입니다.
핵심은 worktree가 저장소를 복제하지 않는다는 점입니다. Git 공식 문서 기준으로 linked worktree는 HEAD, index 같은 per-worktree 파일은 따로 갖고, 저장소의 공통 데이터는 공유합니다. 그래서 디스크를 크게 낭비하지 않으면서도 작업 디렉터리는 분리됩니다.
flowchart TD
REPO["하나의 Git 저장소"] --> MAIN["원래 작업 디렉터리
예: main"]
REPO --> FEAT["새 worktree
../feat-login"]
MAIN --> M1["기존 작업 유지"]
FEAT --> F1["feat/login 브랜치 작업"]
REPO --> SHARED["객체 DB / refs 공유"]
MAIN --> LOCAL1["HEAD / index / 파일은 개별"]
FEAT --> LOCAL2["HEAD / index / 파일은 개별"]
classDef repo fill:#c5dcef,stroke:#6b9ac4,color:#333
classDef work fill:#c0ecd3,stroke:#67a97c,color:#333
classDef meta fill:#fde8c0,stroke:#d9a441,color:#333
class REPO,SHARED repo
class MAIN,FEAT,M1,F1 work
class LOCAL1,LOCAL2 meta이 예제를 한 번 써 보면, worktree를 “멀티 에이전트 전용 고급 기능"이 아니라 브랜치별 작업공간을 분리하는 일상적인 도구 로 받아들이게 됩니다. 그리고 이 감각이 있어야 뒤의 hotfix나 병렬 작업 예제도 쉬워집니다.
2) 공식 문서 대표 예제: 작업 도중 긴급 hotfix가 들어왔을 때
Git 공식 문서가 가장 설득력 있게 드는 사례는 이겁니다. 리팩터링 중인데 상사가 와서 당장 긴급 수정부터 하라고 하는 상황입니다. 보통은 git stash 로 현재 작업을 치워 두고 hotfix를 했다가 다시 돌아옵니다. 하지만 작업 트리가 너무 지저분하면 stash/pop 과정 자체가 스트레스가 됩니다.
문서가 제안하는 대안은 새 linked worktree를 하나 더 만드는 것입니다.
# 현재 작업은 그대로 둔 채 긴급 수정용 worktree 생성
git worktree add -b emergency-fix ../temp master
# 긴급 수정 작업
cd ../temp
# ... 수정 ...
git commit -am "fix: urgent production issue"
# 작업이 끝나면 제거
cd -
git worktree remove ../temp
이 흐름이 좋은 이유는 현재 작업 디렉터리를 건드리지 않는다는 점입니다. 즉 긴급 대응이 끝난 뒤 다시 원래 폴더로 돌아오면, 방금 전까지 하던 리팩터링 컨텍스트가 그대로 살아 있습니다. worktree가 편한 이유를 한 문장으로 줄이면, 컨텍스트 스위칭을 stash가 아니라 폴더 전환으로 바꾸는 기능 이라고 볼 수 있습니다.
flowchart TD
START["리팩터링 작업 중"] --> BUG["긴급 버그 수정 요청"]
BUG --> CREATE["별도 hotfix worktree 생성"]
CREATE --> FIX["새 폴더에서 수정 / 커밋"]
FIX --> REMOVE["worktree 제거"]
REMOVE --> BACK["원래 작업 폴더로 복귀"]
classDef input fill:#c5dcef,stroke:#6b9ac4,color:#333
classDef process fill:#fde8c0,stroke:#d9a441,color:#333
classDef result fill:#c0ecd3,stroke:#67a97c,color:#333
class START,BUG input
class CREATE,FIX,REMOVE process
class BACK result작업이 자주 끊기는 환경일수록 이 예제의 가치가 커집니다. AI 에이전트 세션을 오래 유지하는 경우에도 마찬가지입니다. 한 세션은 계속 피처 개발을 하고, 다른 세션은 hotfix만 처리한 뒤 바로 닫을 수 있기 때문입니다.
3) 기존 브랜치를 다른 폴더로 체크아웃하는 예제와 detached HEAD 함정
두 번째로 자주 쓰는 예제는 이미 존재하는 브랜치를 다른 디렉터리에서 여는 경우입니다.
# 이미 존재하는 로컬 브랜치를 별도 폴더에서 열기
git worktree add ../review feature/review-copy
# 원격 브랜치를 로컬 브랜치로 받아서 worktree 만들기
git worktree add staging -b staging origin/staging
# 필요하다면 upstream 명시
git -C staging branch --set-upstream-to=origin/staging staging
여기서 많이 헷갈리는 포인트가 있습니다. KKamJi 글이 강조하듯이, 아래처럼 원격 브랜치를 직접 가리키는 방식은 detached HEAD 상태를 만들 수 있습니다.
# 주의: detached HEAD 상태가 될 수 있는 패턴
git worktree add staging origin/staging
이 방식이 항상 틀린 것은 아니지만, 보통 실무에서는 “지속적으로 커밋하고 pull/push 할 로컬 브랜치” 가 필요합니다. 그래서 새 worktree를 만들 때는 -b staging origin/staging 처럼 로컬 브랜치를 하나 만들고 원격을 추적하게 두는 방식 이 더 안전합니다.
flowchart TD
START["원격 브랜치 worktree 필요"] --> Q1{"로컬 브랜치도 필요한가?"}
Q1 -->|"예"| SAFE["git worktree add staging -b staging origin/staging"]
Q1 -->|"아니오 / 임시 확인"| DETACH["git worktree add staging origin/staging"]
SAFE --> RESULT1["일반적인 pull / push 흐름 가능"]
DETACH --> RESULT2["detached HEAD 가능"]
classDef input fill:#c5dcef,stroke:#6b9ac4,color:#333
classDef decision fill:#fde8c0,stroke:#d9a441,color:#333
classDef good fill:#c0ecd3,stroke:#67a97c,color:#333
classDef warn fill:#ffc8c4,stroke:#d47a75,color:#333
class START input
class Q1 decision
class SAFE,RESULT1 good
class DETACH,RESULT2 warn정리하면, “읽기 전용 확인용” worktree와 “실제로 계속 작업할” worktree를 구분해서 생각하면 쉽습니다. 후자라면 로컬 브랜치와 upstream을 명시적으로 챙기는 것이 좋습니다.
4) 멀티 에이전트 / 병렬 작업 예제: 역할별로 worktree를 나누기
이제 git worktree 를 왜 멀티 에이전트 개발과 연결해 이야기하는지 예제로 보면 더 쉽습니다. KKamJi 글은 각 AI 에이전트에게 독립된 worktree를 할당해 컨텍스트 분리와 충돌 위험 감소를 노리는 패턴을 소개합니다.
# 예: UI 수정, 버그 수정, 문서 작업을 병렬로 분리
git worktree add ../feat-ui-update -b feat/ui-update main
git worktree add ../fix-payment-bug -b fix/payment-bug main
git worktree add ../docs-workflow-guide -b docs/workflow-guide main
# 각 폴더에서 다른 세션/에이전트 실행
cd ../feat-ui-update && claude
cd ../fix-payment-bug && claude
cd ../docs-workflow-guide && claude
이 방식의 장점은 명확합니다. 세 에이전트가 같은 저장소를 바라보더라도, 실제 수정은 서로 다른 폴더에서 일어납니다. 그러면 한 에이전트의 미완성 변경이 다른 에이전트의 작업 디렉터리를 더럽히지 않습니다. 다만 여기서 중요한 것은 작업 디렉터리 충돌이 줄어드는 것과 병합 충돌이 사라지는 것은 다르다 는 점입니다. 원문도 이 부분을 분명히 짚습니다.
즉 병렬 작업에서 진짜 중요한 것은 worktree를 만드는 것 자체보다, 어떤 브랜치를 누가 맡는지, 어떤 파일 범위를 건드리는지, 언제 git fetch 해서 통합 리스크를 확인할지를 먼저 정하는 것입니다.
flowchart TD
REQ["하나의 저장소에서 여러 작업 요청"] --> SPLIT["브랜치 / worktree 단위로 분리"]
SPLIT --> UI["feat/ui-update"]
SPLIT --> BUG["fix/payment-bug"]
SPLIT --> DOC["docs/workflow-guide"]
UI --> AG1["에이전트 A"]
BUG --> AG2["에이전트 B"]
DOC --> AG3["에이전트 C"]
AG1 --> MERGE["최종 통합 단계"]
AG2 --> MERGE
AG3 --> MERGE
classDef input fill:#c5dcef,stroke:#6b9ac4,color:#333
classDef branch fill:#fde8c0,stroke:#d9a441,color:#333
classDef worker fill:#c0ecd3,stroke:#67a97c,color:#333
classDef output fill:#e0c8ef,stroke:#9b77b0,color:#333
class REQ,SPLIT input
class UI,BUG,DOC branch
class AG1,AG2,AG3 worker
class MERGE output이 패턴은 꼭 AI 에이전트가 아니어도 유효합니다. 사람 팀원끼리 병렬 작업할 때도 동일하게 적용됩니다. 다만 여러 에이전트를 붙일수록 의존성 설치는 각 worktree에서 따로 필요할 수 있다는 점은 꼭 기억해야 합니다. KKamJi 글도 node_modules, venv 같은 디렉터리는 worktree마다 별도 준비가 필요하다고 설명합니다.
5) 정리와 복구 예제: 끝난 worktree는 어떻게 치우고, 꼬였을 때는 어떻게 살릴까
worktree는 만드는 것보다 정리할 때 더 중요해집니다. Git 공식 문서 기준으로 linked worktree를 다 썼다면 git worktree remove 로 제거하는 것이 기본입니다. 그리고 디렉터리를 수동으로 지워 버렸거나 위치를 옮겨 연결 정보가 꼬였을 때는 prune, repair 를 알아 두는 편이 안전합니다.
# 현재 연결된 worktree 목록 확인
git worktree list
# 작업이 끝난 worktree 제거
git worktree remove ../feat-login
# 수동 삭제 등으로 stale 메타데이터가 남았을 때 정리
git worktree prune
# worktree를 옮기거나 연결이 꼬였을 때 복구
git worktree repair
이 명령들을 알고 있으면 “폴더는 없는데 Git은 여전히 있다고 생각하는 상태” 나 “폴더를 옮겼더니 연결이 깨진 상태” 를 덜 당황하고 다룰 수 있습니다. 특히 worktree를 많이 쓰는 팀일수록, cleanup을 습관으로 두지 않으면 목록이 금방 지저분해집니다.
flowchart TD
LIST["git worktree list"] --> DONE1{"작업이 끝났는가?"}
DONE1 -->|"예"| REMOVE["git worktree remove "]
DONE1 -->|"아니오"| KEEP["유지"]
REMOVE --> CHECK{"메타데이터가 남았는가?"}
CHECK -->|"예"| PRUNE["git worktree prune"]
CHECK -->|"연결이 깨짐"| REPAIR["git worktree repair"]
CHECK -->|"아니오"| CLEAN["정리 완료"]
classDef input fill:#c5dcef,stroke:#6b9ac4,color:#333
classDef decision fill:#fde8c0,stroke:#d9a441,color:#333
classDef process fill:#c0ecd3,stroke:#67a97c,color:#333
class LIST input
class DONE1,CHECK decision
class REMOVE,KEEP,PRUNE,REPAIR,CLEAN process 6) bare repository와 wt CLI는 언제 고려하면 좋을까
여기까지 예제를 따라오면, 일반 저장소에서도 git worktree 를 충분히 유용하게 쓸 수 있다는 점이 먼저 보입니다. 그래서 bare repository는 출발점이라기보다 worktree를 많이 운영하게 된 다음에 고려할 전략 으로 이해하는 편이 좋습니다.
KKamJi 글이 bare repository 방식을 추천하는 이유는 모든 브랜치를 동등한 worktree로 관리하고 싶기 때문입니다. 루트 디렉터리를 작업 폴더가 아니라 Git 데이터베이스와 제어 영역으로 두면, main/, staging/, feat/login/ 같은 worktree들이 모두 같은 위상으로 놓입니다. 멀티 에이전트 운영에서는 이런 대칭성이 관리하기 편합니다.
또 원문이 소개하는 wt CLI도 같은 맥락입니다. 이 도구의 핵심은 Git의 새 기능을 만드는 것이 아니라, init, add, status, pull 같은 자주 반복되는 절차를 표준 명령으로 줄여 운영 실수를 덜 나게 만드는 것 입니다. worktree를 가끔 한두 개 쓰는 정도라면 기본 Git 명령만으로 충분하지만, 여러 브랜치와 여러 작업공간을 매일 다룬다면 표준 래퍼를 두는 편이 확실히 편해집니다.
핵심 요약
- 가장 먼저 익혀야 할 패턴은
git worktree add ../feat-login -b feat/login main처럼 새 기능 작업을 별도 폴더로 분리하는 예제입니다. - 공식 문서가 보여 주는 대표 사례는 긴급 hotfix를 새 worktree에서 처리하고, 끝나면 제거한 뒤 원래 작업으로 돌아오는 흐름입니다.
- 원격 브랜치를 worktree로 열 때는
detached HEAD를 피하려고 로컬 브랜치와 upstream을 함께 챙기는 쪽이 실무적으로 안전합니다. - 멀티 에이전트 환경에서 worktree의 진짜 가치는 저장소 복제가 아니라 작업 디렉터리 분리와 컨텍스트 격리 에 있습니다.
git worktree remove,prune,repair를 알고 있으면 많이 쓰는 환경에서도 정리와 복구가 수월합니다.- bare repository와
wt같은 래퍼 CLI는 worktree 사용량이 커진 뒤에 운영 표준화를 위해 도입하는 전략으로 보면 됩니다.
결론
git worktree 를 어렵게 느끼게 만드는 것은 개념 자체보다, 언제 어떤 예제로 감을 잡아야 하는지 감이 없기 때문입니다. 그래서 처음에는 이 글의 순서대로 새 기능 분리 -> 긴급 hotfix -> 기존 브랜치 체크아웃 -> 병렬 작업 -> 정리와 복구 순서로 직접 해 보는 것이 가장 좋습니다.
그 흐름만 몸에 익으면 worktree는 특수한 고급 기능이 아니라, 브랜치 작업을 더 안전하고 덜 번거롭게 만드는 기본 도구로 자리 잡게 됩니다.