Skip to main content

이 노트는 아래 출처를 AI 도구 클립을 활용하여 재구성한 것입니다. 상세한 정보는 원문 방문을 권장합니다.

원문 출처: https://git-scm.com/docs/git-worktree

핵심 요약

git worktree는 하나의 저장소로 여러 작업 디렉터리를 만들어 동시에 다른 브랜치나 커밋을 작업할 수 있게 해주는 기능입니다.

긴급 패치, 대규모 리팩터링, 실험 코드 분리 등에 특히 유용하며, 잘만 쓰면 "브랜치 전환 지옥"에서 벗어날 수 있습니다.

다만 서브모듈, 강제 삭제(--force) 등은 주의해서 써야 합니다.

git worktree는 무엇이고, 왜 써야 하는가

일반적으로 하나의 Git 저장소에는 하나의 working tree(디렉터리)만 연결됩니다.

git worktree를 쓰면 동일한 저장소(.git) 아래에 여러 개의 working tree를 연결해서, 각 디렉터리마다 다른 브랜치나 커밋을 동시에 체크아웃할 수 있습니다.

스타트업 환경에서 특히 유용한 상황은 다음과 같습니다.

리팩터링 브랜치를 크게 진행 중인데, 갑자기 운영 장애가 나서 긴급 패치를 해야 할 때 기존 작업을 건드리지 않고 다른 디렉터리에서 hotfix를 바로 수행할 수 있습니다.

또는, 한 디렉터리에는 안정 브랜치(main), 다른 디렉터리에는 실험용 브랜치(experiment)를 두고, 번갈아 보며 개발할 수 있습니다.

이때 최초로 git init 또는 git clone으로 만들어진 디렉터리를 "메인 worktree", 이후 git worktree add로 추가한 것들을 "링크된 worktree"라고 부릅니다.

새로운 worktree 추가하기: 가장 많이 쓰는 패턴

새 작업 디렉터리를 만드는 기본 명령은 다음과 같습니다.

git worktree add <path> [<commit-ish>]

<path>는 새 디렉터리 경로, <commit-ish>는 브랜치나 커밋입니다.

가장 자주 쓰는 패턴 몇 가지만 기억해 두면 충분합니다.

새로운 브랜치를 만들면서 worktree 추가:

git worktree add ../feature-x

../feature-x 디렉터리를 만들고, 디렉터리 마지막 이름인 feature-x라는 새 브랜치를 HEAD 기준으로 생성 후 체크아웃합니다.

이미 feature-x 브랜치가 존재하면, 그 브랜치를 새로운 worktree에 체크아웃하려 시도합니다(이미 다른 worktree에서 쓰고 있으면 기본적으로 거부).

기존 브랜치를 다른 디렉터리에서 작업:

git worktree add ../release main

main 브랜치를 ../release 디렉터리에 체크아웃합니다.

하나의 브랜치가 동시에 두 worktree에 체크아웃되는 것은 기본적으로 막혀 있으므로, 이런 형태는 보통 "브랜치 별 1 worktree" 규칙을 유지할 때 사용합니다.

실험용, 브랜치 없는 임시 worktree (detached HEAD):

git worktree add -d ../experiment
# 또는
git worktree add --detach ../experiment

현재 브랜치의 커밋을 그대로 갖고 오지만, 브랜치에는 연결하지 않은 상태에서 시작합니다.

테스트나 실험 코드 작성 후 버릴 때 좋습니다.

완전히 빈 상태의 새로운 브랜치 시작 (orphan):

git worktree add --orphan -b docs ../docs-site

커밋 히스토리가 없는 새로운 브랜치를 만들어, 완전히 빈 루트에서 시작합니다.

문서만 따로 관리하는 브랜치 같은 것을 만들 때 유용합니다.

리모트 브랜치를 자동으로 추측해서 새 브랜치 만들기:

git worktree add --guess-remote ../feature-x

origin/feature-x 같이 리모트에만 있는 브랜치가 있고, 그 이름이 유일하게 매칭되면 그 리모트 브랜치를 기반으로 로컬 브랜치를 만들고 upstream을 설정합니다.

이 동작을 기본값으로 쓰고 싶다면:

git config worktree.guessRemote true

로 설정할 수 있습니다.

worktree 목록과 상태 확인하기

현재 저장소에 연결된 모든 worktree는 다음으로 볼 수 있습니다.

git worktree list

메인 worktree가 제일 먼저 나오고, 이어서 링크된 worktree들이 출력됩니다.

각 줄에는 디렉터리 경로, 체크아웃된 커밋, 브랜치 또는 "detached HEAD" 여부, 그리고 상태(locked, prunable 등)가 표시됩니다.

좀 더 많은 정보를 보고 싶다면:

git worktree list --verbose

여기서는 예를 들어 "locked: portable device에 있음", "prunable: gitdir가 존재하지 않음" 같은 설명이 한 줄 더 붙습니다.

스크립트나 자동화에서 안전하게 파싱하고 싶다면:

git worktree list --porcelain -z

기계가 읽기 좋은 고정 포맷으로 출력되며, 각 worktree마다 worktree, HEAD, branch, locked, prunable 등의 키-값 조합으로 표현됩니다.

이동식 디스크와 장기 보존: lock / unlock

어떤 worktree의 실제 디렉터리가 USB, 외장 하드, 네트워크 드라이브 등에 있을 수 있습니다.

이 경우 디스크가 연결되지 않은 상태에서 Git이 "여기 worktree 디렉터리가 없네? 오래됐으니 청소(prune)해야겠다"라고 판단하면 곤란합니다.

이런 상황에서 사용하는 것이 lock입니다.

git worktree lock <worktree-path> --reason "외장 디스크에 있음"

이렇게 잠그면 해당 worktree는 자동 정리(prune)의 대상이 되지 않고, git worktree move나 git worktree remove로도 쉽게 옮기거나 지울 수 없습니다.

잠금 해제는 다음과 같습니다.

git worktree unlock <worktree-path>

스타트업 환경에서는 dev용 SSD/외장 디스크를 자주 빼고 끼우는 경우가 있는데, 그 위에 올려둔 worktree는 반드시 lock해 두는 편이 안전합니다.

worktree 운영: move, remove, prune, repair

실제 운영에서 자주 쓰는 관리 명령들을 정리해 보면 다음과 같습니다.

디렉터리 위치를 옮길 때:

git worktree move <old-path> <new-path>

메인 worktree와 서브모듈이 있는 worktree는 이 명령으로는 옮길 수 없습니다.

그런 경우에는 OS 명령으로 직접 옮긴 뒤 git worktree repair를 써야 합니다.

worktree 삭제(정상 상태일 때):

git worktree remove <path>

여기서 "정상"이란, 변경사항이 없고(untracked 파일도 없음) 서브모듈도 문제 없는 상태를 말합니다.

작업 중인 내용이 남아 있거나, 서브모듈이 있거나, 뭔가 깨끗하지 않으면 기본적으로 삭제를 거부합니다.

강제로 삭제하려면:

git worktree remove -f <path>
# 잠겨 있는 worktree를 강제 삭제하려면 -f를 두 번
git worktree remove -ff <path>

정리(prune)는 "실제 디렉터리는 사라졌지만, .git 내부에 관리 정보만 남아 있는" 좀비 worktree 정보를 치우는 작업입니다.

git worktree prune --dry-run
git worktree prune --expire "30 days ago"

--dry-run으로 무엇을 지울지 먼저 확인한 뒤, 만료 기간을 지정해 오래된 것만 지우는 식으로 운용할 수 있습니다.

마지막으로 repair는 "사람이 직접 디렉터리를 옮기거나 복사해서 연결이 끊어진 경우"에 쓰는 복구 도구입니다.

메인 worktree를 통째로 다른 경로로 옮긴 경우:

# 새 위치에서
git worktree repair

링크된 worktree의 디렉터리만 수동으로 옮긴 경우:

# 옮겨진 worktree 경로에서
git worktree repair

메인과 여러 링크된 worktree를 모두 수동으로 옮긴 경우:

# 새 메인 worktree에서
git worktree repair /new/path/worktree-a /new/path/worktree-b

이렇게 하면 내부 .git/worktrees/…에 저장된 연결 정보가 다시 맞춰집니다.

내부 구조와 ref 공유 방식 이해하기

조금만 구조를 이해해 두면, 나중에 직접 .git 내부를 만져야 할 때 위험을 줄일 수 있습니다.

메인 worktree의 .git 디렉터리를 $GIT_COMMON_DIR이라고 하고, 각 링크된 worktree마다 .git/worktrees/<id> 같은 "개인 디렉터리"가 하나씩 생깁니다.

링크된 worktree의 .git에는 실제 디렉터리가 아니라 이 개인 디렉터리 위치가 적혀 있습니다.

여기서 중요한 규칙은:

HEAD, index 등은 worktree마다 따로 존재하지만, 일반적인 브랜치 ref(refs/heads/*)는 공유된다는 점입니다.

즉, master 브랜치 ref는 하나만 있고, 어느 worktree에서 커밋하든 같은 브랜치 ref가 움직입니다.

반면 HEAD는 각 worktree마다 다르고, refs/bisect, refs/worktree, refs/rewritten 같은 일부 ref도 worktree별로 분리됩니다.

다른 worktree의 HEAD 등을 직접 보고 싶다면, $GIT_DIR를 직접 건드리기보다 다음 같은 형식을 쓰는 것이 안전합니다.

git rev-parse main-worktree/HEAD
git rev-parse worktrees/foo/HEAD

이런 식으로 "main-worktree" 또는 "worktrees/<id>" 접두어를 통해 다른 worktree의 per-worktree ref에 접근할 수 있습니다.

요약하면: .git 내부 경로를 직접 추측하지 말고, 가능하면 git rev-parse --git-path나 git rev-parse <ref> 같은 명령으로 경로·ref를 얻는 습관이 좋습니다.

worktree별 설정 분리하기: worktreeConfig

기본적으로 git config는 저장소 전체에 하나의 설정 파일(.git/config)을 공유합니다.

하지만 여러 worktree를 쓰다 보면, worktree마다 다른 설정을 쓰고 싶은 경우가 생깁니다. 예를 들어 어떤 worktree에서는 sparse checkout을 쓰고, 어떤 곳에서는 안 쓰고 싶은 경우입니다.

이럴 때 사용하는 것이 extensions.worktreeConfig입니다.

git config extensions.worktreeConfig true

이 옵션을 켜면, 각 worktree를 위한 별도 설정 파일이 생깁니다.

git config --worktree user.name "Dev for feature-x"

이렇게 --worktree를 붙이면, 해당 worktree 전용 설정 파일(.git/worktrees/<id>/config.worktree)에 값이 기록되고, 글로벌/저장소 공통 설정보다 나중에 읽혀서 override됩니다.

주의해야 할 것은, 이 모드를 켜면 core.worktree, core.bare 같은 항목은 공유 설정(.git/config)에 두면 안 되고, 메인 worktree의 config.worktree로 옮겨야 한다는 점입니다.

또한 worktree.useRelativePaths=true로 설정하면 worktree 간 링크를 상대 경로로 유지하는데, 이는 저장소를 다른 경로로 옮길 가능성이 있을 때 유리하지만, 오래된 Git 버전과 호환성이 떨어질 수 있습니다.

실전 사용 패턴: 스타트업에서 자주 쓸 시나리오

  1. 긴급 패치용 임시 worktree

리팩터링 중인 브랜치에서 손대기 싫을 때:

# 메인 worktree에서
git worktree add -b emergency-fix ../temp main
cd ../temp
# 수정 후
git commit -a -m "emergency fix"
cd -
git worktree remove ../temp

기존 작업 디렉터리는 그대로 두고, 임시 디렉터리에서만 패치를 하고 바로 제거합니다.

  1. 리뷰용 "읽기 전용" worktree

코드 리뷰하거나 리포트용으로 로그를 보는 전용 디렉터리를 둘 수 있습니다.

git worktree add ../review main

여기서는 의도적으로 커밋을 하지 않거나, 별도 계정 이름을 쓰도록 git config --worktree user.name "Reviewer"로 설정할 수도 있습니다.

  1. 실험·프로토타입 전용 worktree

실험 프로젝트를 쉽게 만들고 버리기 위해 detached HEAD를 사용할 수 있습니다.

git worktree add -d ../experiment
cd ../experiment
# 막 코드 써보고, 필요 없으면 그냥 디렉터리 삭제하거나 remove
git worktree remove ../experiment

브랜치 히스토리를 더럽히지 않고 실험 후 버리는 패턴입니다.

주의해야 할 점과 운영 팁

git worktree 기반의 "다중 체크아웃" 기능은 여전히 서브모듈 지원이 완전하지 않습니다.

서브모듈이 많은 모노레포나 superproject에서 여러 worktree를 만들면 예상치 못한 문제가 생길 수 있어, 이런 경우에는 신중하게 검토해야 합니다.

--force 옵션은 강력하지만 위험합니다.

특히 git worktree remove -ff는 잠겨 있는 worktree까지도 강제 삭제하기 때문에, 실제로 필요한지 두 번 확인하고 사용해야 합니다.

또한 하나의 브랜치를 여러 worktree에서 동시에 체크아웃할 수는 있지만, 충돌 가능성이 높고 헷갈립니다.

운영 상으로는 "브랜치 하나당 최대 하나의 worktree"라는 팀 규칙을 두면 사고를 줄일 수 있습니다.

마지막으로, 여러 worktree를 쓰다 보면 어느 디렉터리에서 어떤 브랜치가 열려 있는지 헷갈립니다.

주기적으로 git worktree list를 확인하고, 쓰지 않는 worktree는 과감히 remove 또는 prune하는 습관을 들이면 관리 비용이 크게 줄어듭니다.

인사이트

git worktree는 "브랜치를 빠르게 바꾸는 도구"가 아니라 "브랜치를 물리적으로 분리해서 동시에 작업하는 도구"라고 보면 이해가 쉽습니다.

스타트업처럼 요구사항이 수시로 바뀌고 긴급 이슈가 자주 들어오는 환경에서는, 긴급 대응과 실험, 리팩터링을 서로 간섭 없이 병렬로 진행할 수 있게 해주는 강력한 레버리지입니다.

실제로는 다음 세 가지만 팀에 공유해도 충분히 생산성이 올라갑니다: git worktree add로 새 작업 디렉터리 만들기, git worktree list로 상태 확인하기, 그리고 필요 없을 때 git worktree remove로 정리하기.

필요해질 때마다 lock, repair, worktree별 config 같은 고급 기능을 점진적으로 도입하면, 레포 규모가 커져도 깔끔하게 운영할 수 있습니다.

출처 및 참고 : Git - git-worktree Documentation

이 노트는 보도·비평·교육·연구 목적으로 작성되었습니다. 저작권 문의가 있으시면 에서 알려주세요.

틸노트는 사용자가 AI를 활용해 노트를 쉽게 작성하거나 편집할 수 있는 서비스입니다.

AI 스퀘어 단톡방에 함께해요

AI 활용과 틸노트 사용 팁을 나누는 오픈채팅방입니다. 입장 비밀번호는 tilnote입니다.

참여하기