
Claude Code를 git worktree로 병렬 실행하는 구현 절차 — untracked 파일 소실과 포트 충돌, 3가지
요약
Claude Code를 git worktree와 결합하여 여러 태스크를 병렬로 실행하는 구체적인 방법과 주의사항을 다룹니다. untracked 파일 소실, node_modules 관리, 포트 충돌 문제를 해결하는 실무적인 절차를 제공합니다.
핵심 포인트
- git worktree를 통해 브랜치 전환 없이 Claude Code 세션을 병렬로 운영 가능
- .env 등 untracked 파일은 worktree 생성 시 수동 복사 또는 심볼릭 링크 필요
- node_modules 독립성에 따른 디스크 및 시간 소모 주의
- 여러 worktree에서 개발 서버 실행 시 포트 충돌 방지 필요
- 작업 종료 시 브랜치 삭제 전 반드시 worktree를 먼저 제거해야 함
예상 독자는 Claude Code로 여러 태스크를 병렬로 진행하고 싶은 엔지니어입니다. 하나의 리포지토리(Repository)에서 동시에 2개 이상의 태스크를 Claude Code에 던졌다가, 브랜치 전환 과정에서 서로의 변경 사항을 망가뜨려 본 경험이 있는 분들을 위해 작성합니다.
전제 환경:
- Claude Code (2026년 7월 시점의 CLI 버전)
- Git 2.40 이상 (
git worktree를 안정적으로 사용할 수 있는 버전) - Node.js 22.x를 상정한 프로젝트 (
node_modules관련 내용을 다루기 위함)
git worktree 자체의 일반적인 사용법은 설명하지 않습니다. "Claude Code와 조합했을 때 무엇이 문제가 되는가"에 집중하여 작성합니다.
- 하나의
.git으로부터 여러 작업 디렉토리(worktree)를 생성하여, 그곳에 Claude Code를 하나씩 실행하면 브랜치 전환 없이 병렬로 태스크를 진행할 수 있습니다. - 하지만
.env와 같은 untracked 파일은 worktree로 인계되지 않습니다. → 실행 직후 환경 변수 부족으로 종료됩니다. node_modules도 worktree마다 독립됩니다. → 아무 생각 없이 병렬로npm install을 실행하면 시간과 디스크를 소모합니다.- 개발 서버를 여러 worktree에서 동시에 띄우면 포트(Port)가 충돌합니다.
먼저 새로운 태스크용 worktree를 생성합니다.
# 메인 작업 디렉토리에서 실행
git worktree add ../myapp-feature-a -b feature-a
git worktree add ../myapp-feature-b -b feature-b
이렇게 하면 ../myapp-feature-a와 ../myapp-feature-b라는 각각 독립된 체크아웃(Checkout) 대상이 생깁니다. 동일한 .git 오브젝트 DB를 공유하므로 커밋 히스토리 참조는 순식간이며, 풀 클론(Full Clone)보다 디스크 소비도 훨씬 적습니다.
각 디렉토리에서 Claude Code를 별도의 세션으로 실행합니다.
cd ../myapp-feature-a && claude
cd ../myapp-feature-b && claude
이제 두 개의 Claude Code 세션이 동일한 리포지토리의 서로 다른 브랜치를 동시에 다룰 수 있는 상태가 됩니다. 한쪽에서 git checkout을 하더라도 다른 쪽의 작업 트리(Worktree)에는 전혀 영향을 주지 않습니다.
태스크가 끝나면 worktree를 정리합니다.
git worktree remove ../myapp-feature-a
git worktree prune
remove를 잊고 git branch -d feature-a만 실행하면 다음과 같은 에러가 발생하며 거부됩니다.
error: cannot delete branch 'feature-a' checked out at '/path/to/myapp-feature-a'
worktree 삭제가 먼저, 브랜치 삭제는 나중이라는 순서를 기억해 두세요.
git worktree add는 "Git이 추적하고 있는 파일"만 체크아웃합니다. .env나 .env.local은 대개 .gitignore에 포함되어 있으므로, 새로운 worktree에는 처음부터 존재하지 않습니다.
Error: Missing required environment variable: DATABASE_URL
와 같은 에러로 인지하는 경우가 많습니다. 회피 방법은 간단합니다. worktree 생성 직후 수동으로 복사하거나 심볼릭 링크(Symbolic Link)를 겁니다.
git worktree add ../myapp-feature-a -b feature-a
cp .env ../myapp-feature-a/.env
빈번하게 worktree를 생성한다면, git worktree add 이후에 자동으로 복사해 주는 래퍼 스크립트(Wrapper Script)를 하나 작성해 두면 사고를 줄일 수 있습니다.
worktree는 작업 트리가 다르기 때문에 node_modules도 당연히 별도로 존재하게 됩니다. 동일한 의존성(Dependency)을 worktree 개수만큼 설치하게 되어 디스크와 시간을 소비합니다. 3개 병렬로 npm install을 돌리면, 성능이 낮은 CI 러너(Runner) 정도의 머신에서는 몇 분 단위로 대기해야 할 수도 있습니다.
pnpm을 사용하는 프로젝트라면 글로벌 스토어 (Global Store)가 공유되므로 npm이나 yarn보다는 피해가 적습니다. npm만 사용할 수 있는 경우에는 node_modules를 worktree 간에 심볼릭 링크 (Symbolic Link)로 연결하는 방법도 있지만, 의존성 (Dependency) 버전이 worktree마다 다를 것으로 예상되는 작업(라이브러리의 메이저 업데이트 검증 등)에서는 그대로 사고가 발생합니다. 그런 경우에는 순순히 풀 인스톨 (Full Install)을 하는 것이 더 안전합니다.
npm run dev가 기본적으로 3000번 포트를 사용하도록 설정되어 있다면, 두 번째 worktree에서 동일한 명령어를 실행하는 순간
Error: listen EADDRINUSE: address already in use :::3000
메시지와 함께 종료됩니다. worktree마다 PORT 환경 변수를 변경하거나(앞서 언급한 .env 복사 시 PORT=3001과 같이 수정해 두는 방식), dev 스크립트 측을 포트 가변형으로 만들어 두면(예: next dev -p $PORT) Claude Code가 병렬로 서버를 띄워 동작 확인을 수행하는 작업에서도 충돌이 발생하지 않습니다.
worktree마다 .claude/settings.local.json의 권한 허용 리스트도 리셋됩니다 (이 파일 자체는 대개 gitignore 대상입니다). 병렬 작업의 첫 실행 시에만 Bash 실행 허용 프롬프트가 양쪽 worktree 모두에서 나타나는 것은 이것이 원인이며, 버그가 아닙니다. 빈번하게 worktree를 전환하는 운영 방식이라면, 프로젝트 공통으로 허용하고 싶은 명령어는 gitignore 대상이 아닌 .claude/settings.json에 모아두면 worktree를 넘나들더라도 다시 묻지 않게 됩니다.
- git worktree + Claude Code를 사용하면, 브랜치 전환을 거치지 않고 여러 작업을 병렬로 진행할 수 있습니다.
.env는 untracked 상태이므로 worktree로 인계되지 않습니다 $\rightarrow$ 명시적으로 복사해야 합니다.node_modules는 worktree마다 독립적입니다 $\rightarrow$ 의존성이 같다면 pnpm이나 심볼릭 링크로 절약할 수 있습니다.- 개발 서버는
PORT를 worktree마다 변경하지 않으면 충돌합니다. - 정리는
git worktree remove를 먼저 하고, 브랜치 삭제는 그 다음에 합니다.
AI 자동 생성 콘텐츠
본 콘텐츠는 Qiita AI의 원문을 AI가 자동으로 요약·번역·분석한 것입니다. 원 저작권은 원저작자에게 있으며, 정확한 내용은 반드시 원문을 확인해 주세요.
원문 바로가기