PUBLISHED
Git Worktree
작성일: 2026.02.02

Git으로 여러 작업을 병렬로 진행하다 보면 브랜치 전환 자체가 비용이 되는 순간이 잦다. 기능 개발 중에 긴급 핫픽스를 처리해야 하거나, PR 리뷰를 위해 다른 브랜치를 실행해 봐야 하는 상황에서 git checkout과 stash를 반복하는 방식은 작업 흐름을 지속적으로 끊는다. 이 과정에서 실수가 발생하기도 하고, 현재 어떤 작업 맥락에 있는지 놓치는 경우도 많다.
Git Worktree는 이러한 문제를 브랜치 전환이 아닌 작업 공간 분리라는 방식으로 해결한다. 하나의 Git 저장소를 공유하면서 여러 작업 디렉터리를 동시에 운용할 수 있게 함으로써, 각 브랜치를 독립적인 작업 환경으로 다룰 수 있게 한다. 작업 단위가 브랜치가 아니라 폴더가 되면서, 컨텍스트 스위칭 비용이 눈에 띄게 줄어들고 병렬 작업이 구조적으로 가능해진다.
Git Worktree 핵심 명령어 정리
명령어 | 설명 | 비고 |
|---|---|---|
git worktree add <경로> <브랜치> | 새 워크트리 생성 | 경로는 프로젝트 폴더 바깥 |
git worktree add <경로> --detach | 브랜치 없는 임시 워크트리 | PR 리뷰, 테스트용 |
git worktree list | 모든 워크트리 목록 조회 | 브랜치 점유 상태 확인 |
git worktree remove <경로> | 워크트리 안전 삭제 | 변경 사항 있으면 삭제 불가 |
git worktree prune | 잘못 남은 워크트리 정리 | 폴더 직접 삭제 후 |
git worktree lock <경로> | 워크트리 잠금 | 외장/네트워크 드라이브 |
git worktree unlock <경로> | 워크트리 잠금 해제 | |
git worktree repair | 워크트리 경로 복구 | 폴더 이동 후 |
문제 해결 방법 및 주의사항
워크트리 생성 위치가 잘못된 경우
워크트리를 기존 프로젝트 디렉터리 안에 생성하면 안 된다. 이 경우 Git이 워크트리 디렉터리를 원래 레포지토리의 untracked 파일로 인식한다.
# 프로젝트 폴더 안에 워크트리 생성 (실수)
git worktree add project/feature-cool feature/cool이렇게 하면 project/feature-cool 폴더가 원래 레포지토리의 untracked 파일로 보인다. git status를 실행하면 불필요한 파일이 화면에 많이 나온다.
# 상위 폴더에 워크트리 생성
git worktree add ../feature-cool feature/cool
cd ../feature-cool
git status이제 feature/cool 브랜치를 별도의 디렉터리에서 안전하게 다룰 수 있다. 워크트리는 원래 폴더와 분리되어 있으므로 git status가 지저분해지지 않는다.
동일 브랜치를 동시에 열 수 없음 (브랜치 충돌 방지)
Git은 동일한 브랜치를 두 개 이상의 워크트리에서 동시에 체크아웃할 수 없다. 이 경우 에러가 발생한다.
# 워크트리1
git worktree add ../feature-a feature/a
cd ../feature-a
# 이 브랜치가 이미 체크아웃되어 있음
# 다른 위치에서 다시 같은 브랜치를 열려고 하면
git worktree add ../feature-a-copy feature/a
# fatal: 'feature/a' is already used by worktree ...위와 같이 같은 브랜치를 동시에 열면 Git이 충돌을 막는다.
# detach 옵션으로 임시 워크트리 생성
git worktree add ../temp-check --detach
cd ../temp-check
# 임시 실행이나 테스트 목적이라면 이 상태로 충분
git status--detach 옵션은 기존 브랜치를 건드리지 않고 작업만 실행하려는 경우 유용하다.
워크트리마다 의존성은 별도
워크트리는 독립적인 디렉터리이므로 기존 워크트리의 의존성(예: node_modules)을 공유하지 않는다.
# 새 워크트리 생성
git worktree add ../feature-auth feature/auth
cd ../feature-auth
# 이 워크트리에는 node_modules가 없다
ls node_modules # (없음)
# 의존성 설치
npm install워크트리는 하나의 저장소를 여러 디렉터리로 나눈 것일 뿐, 파일 시스템 관점에서 각각 별도의 프로젝트다. 따라서 의존성 설치는 각 워크트리별로 수행해야 한다.
폴더를 직접 삭제했을 때
워크트리를 rm -rf로 강제 삭제하면 Git 메타데이터에는 그 워크트리가 남아 있을 수 있다. 이런 상황에서는 git worktree prune으로 정리해야 한다.
# 실수로 워크트리 폴더를 직접 삭제
rm -rf ../feature-bugfix
# 이 상태에서 prune 실행
git worktree prune
# prune된 워크트리가 Git 메타데이터에서 제거된다이렇게 하면 Git의 워크트리 목록과 실제 폴더가 일치하게 된다.
워크트리를 제거할 때는 단순히 디렉터리만 지우지 말고 git worktree remove를 이용하는 것이 안전하다. 이 명령어는 워크트리 메타데이터를 정리하며, 브랜치가 해당 워크트리에서 체크아웃된 상태인지 확인한다.
# 워크트리 제거
git worktree remove ../feature-ui이 명령은 실제 디렉터리를 삭제하고, Git이 관리하는 워크트리 목록에서도 제거한다.
필요하다면 브랜치는 별도로 삭제한다.
베어 레포지토리(Bare Repository) 전략
Git Worktree를 제대로 활용하려면, 결국 레포지토리 구조를 어떻게 가져갈 것인가에 대한 고민으로 이어진다. 이때 가장 깔끔한 방식이 베어 레포지토리를 중심에 두는 전략이다. 베어 레포지토리는 소스 코드 없이 Git 데이터베이스만 존재하는 저장소다. 즉, .git 디렉터리만 따로 떼어내 하나의 “중앙 관리소”로 두고, 실제 작업은 모두 Worktree에서만 수행한다.
일반적인 Git 저장소는 다음과 같은 구조를 가진다.
project/
├─ .git/
├─ src/
├─ package.json반면, 베어 레포지토리 전략에서는 구조가 완전히 달라진다.
project-root/
├─ .bare/ # Git 데이터베이스만 존재
├─ main/ # main 브랜치 작업 공간
├─ feature-a/ # feature 브랜치
├─ hotfix/ # hotfix 브랜치.bare는 Git의 “두뇌” 역할만 하고, main, feature-a, hotfix 같은 폴더들이 실제 작업 공간이 된다. 이 구조에서는 폴더 자체가 작업 컨텍스트가 된다.
초기 세팅 방법
먼저 프로젝트를 담을 루트 폴더를 만든다.
mkdir project-root
cd project-root그 다음, 원격 레포지토리를 베어 레포지토리로 clone한다. 이 시점에서 .bare 폴더에는 소스 코드가 없고 Git 데이터만 존재한다.
git clone --bare <REPO_URL> .bare이제 첫 번째 작업 공간(main 브랜치)을 만든다. 이렇게 하면 main/ 폴더가 생성되고, 그 안에 실제 소스 코드가 체크아웃된다. 이제부터는 모든 개발 작업을 워크트리 폴더 안에서만 진행한다.
git worktree add main추가 워크트리 생성 예시
기능 개발을 위한 브랜치를 추가로 열고 싶다면 다음과 같이 한다.
git worktree add feature-login feature/login또는 아직 브랜치가 없다면 새 브랜치를 생성하면서 열 수도 있다.
git worktree add -b feature/search feature-search이제 디렉터리 구조는 다음과 같이 확장된다. 각 폴더는 서로 완전히 독립된 작업 공간이다.
project-root/
├─ .bare/
├─ main/
├─ feature-login/
├─ feature-search/베어 레포지토리 사용 시 반드시 지켜야 할 규칙
가장 중요한 규칙은 .bare 폴더에서는 작업하지 않는 것이다. 여기에는 소스 코드가 없으므로 git pull이나 git merge 같은 명령을 실행하면 오류가 난다. 원격 변경 사항을 가져오고 싶다면 다음 중 하나의 방식만 사용한다.
# 루트에서 Git 데이터만 갱신
git -C .bare fetch# 실제 작업 중인 워크트리에서
cd main
git pull베어 레포지토리 전략을 사용하면 더 이상 “지금 어떤 브랜치에서 작업 중이지?”를 의식할 필요가 없다. 작업 상태는 브랜치 이름이 아니라 어떤 폴더에 들어가 있는지로 자연스럽게 드러난다. main 폴더에 있으면 메인 작업을 하고 있는 것이고, feature-login 폴더에 있으면 해당 기능 개발을 하고 있는 상태다. 작업 맥락을 기억해야 할 대상이 Git 상태가 아니라 파일 시스템이 된다.
이 방식은 동시에 여러 작업을 진행해야 하는 상황에서 특히 효과적이다. 기능 개발 도중에도 핫픽스 작업을 즉시 병행할 수 있고, PR 리뷰를 위해 별도의 워크트리를 만들어 코드를 실제로 실행해 볼 수도 있다. 각 워크트리는 완전히 독립된 디렉터리이기 때문에, 여러 서버를 서로 다른 포트로 동시에 띄우는 것도 어렵지 않다. 필요하다면 워크트리별로 Node.js 버전이나 환경 설정을 분리해, 레거시 유지보수와 신규 개발을 병렬로 진행할 수도 있다.
기능 개발과 핫픽스를 동시에 진행해야 할 때
PR 리뷰용 코드를 실제로 실행해야 할 때
여러 서버를 서로 다른 포트로 동시에 띄워야 할 때
워크트리별로 Node.js 버전이나 환경 설정을 분리해야 할 때
Git Worktree 자체만으로도 충분히 강력하지만, 베어 레포지토리를 함께 사용하면 프로젝트 전체 구조가 한 단계 정리된다. Git의 역할을 “브랜치 전환 도구”에서 “작업 공간 관리 도구”로 바꾸는 느낌에 가깝다. Git 데이터와 소스 코드를 물리적으로 분리하고, 모든 실제 작업은 Worktree에서만 수행한다. 그 결과 폴더 구조 자체가 현재 어떤 작업을 하고 있는지를 설명하는 문맥이 된다.
Git Worktree를 단기적인 실험이 아니라 장기적인 작업 방식으로 가져갈 계획이라면, 베어 레포지토리 전략은 선택이라기보다 거의 필수에 가깝다.