작업트리
Codex 앱에서 worktree를 사용하면 같은 프로젝트 안에서 여러 독립 작업을 서로 방해하지 않고 실행할 수 있습니다. Git 저장소에서는 자동화가 전용 background worktree에서 실행되므로 진행 중인 작업과 충돌하지 않습니다. 버전 관리되지 않는 프로젝트에서는 자동화가 프로젝트 디렉터리에서 직접 실행됩니다. 수동으로 worktree에서 스레드를 시작할 수도 있고, Handoff를 사용해 스레드를 Local과 Worktree 사이에서 이동할 수도 있습니다.
worktree란 무엇인가
Worktree는 내부적으로 Git worktree를 사용하므로 Git 저장소에 속한 프로젝트에서만 작동합니다. worktree는 저장소의 두 번째 사본, 즉 checkout을 만들 수 있게 합니다. 각 worktree는 저장소의 모든 파일 사본을 따로 갖지만 commit, branch 등 metadata(.git 폴더)는 공유합니다. 따라서 여러 branch를 병렬로 checkout하고 작업할 수 있습니다.
용어
- Local checkout: 사용자가 만든 저장소입니다. Codex 앱에서는 간단히 Local이라고도 합니다.
- Worktree: Codex 앱에서 local checkout으로부터 만들어진 Git worktree입니다.
- Handoff: 스레드를 Local과 Worktree 사이에서 이동하는 흐름입니다. Codex는 작업을 안전하게 이동하는 데 필요한 Git 작업을 처리합니다.
worktree를 사용하는 이유
- 현재 Local 설정을 방해하지 않고 Codex와 병렬로 작업합니다.
- foreground 작업에 집중하는 동안 background 작업을 queue합니다.
- 나중에 변경 사항을 검사, 테스트, 협업할 준비가 되었을 때 스레드를 Local로 이동합니다.
시작하기
Worktree에는 Git 저장소가 필요합니다. 선택한 프로젝트가 Git 저장소 안에 있는지 확인하십시오.
-
Worktree를 선택합니다.
새 스레드 보기에서 composer 아래의 Worktree를 선택합니다. 선택적으로 worktree 설정 스크립트를 실행할 로컬 환경을 고릅니다.
-
시작 branch를 선택합니다.
composer 아래에서 worktree의 기준이 될 Git branch를 선택합니다.
main/master, feature branch, unstaged local change가 있는 현재 branch 모두 가능합니다. -
프롬프트를 제출합니다.
작업을 제출하면 Codex가 선택한 branch를 기준으로 Git worktree를 만듭니다. 기본적으로 Codex는 detached HEAD에서 작업합니다.
-
계속 작업할 위치를 선택합니다.
준비되면 worktree에서 직접 계속 작업하거나 스레드를 local checkout으로 hand off할 수 있습니다. local로 또는 local에서 handoff하면 스레드와 코드가 함께 이동하므로 다른 checkout에서 계속할 수 있습니다.
Local과 Worktree 사이에서 작업
Worktree는 local checkout과 비슷하게 보이고 느껴집니다. 차이는 흐름에서 차지하는 위치입니다. Local은 foreground, Worktree는 background로 생각할 수 있습니다. Handoff는 스레드를 둘 사이에서 이동하게 합니다.
내부적으로 Handoff는 두 checkout 사이에서 작업을 안전하게 이동하는 데 필요한 Git 작업을 처리합니다. 이는 Git이 branch 하나를 동시에 한 위치에서만 checkout하도록 허용하기 때문에 중요합니다. worktree에서 branch를 checkout하면 같은 시간에 local checkout에서 그 branch를 checkout할 수 없고, 반대도 마찬가지입니다.
일반적인 경로는 두 가지입니다.
- worktree에서만 작업: 로컬 환경 설정 스크립트로 의존성과 도구가 설치되어 있어 worktree에서 직접 변경을 검증할 수 있을 때 가장 좋습니다.
- 스레드를 Local로 hand off: 일반 IDE 창에서 변경을 읽거나, 기존 개발 서버를 실행하거나, 앱 instance를 하나만 실행할 수 있는 경우처럼 스레드를 foreground로 가져오고 싶을 때 사용합니다.
옵션 1: worktree에서 작업
변경 사항과 함께 worktree에만 머무르고 싶다면 스레드 header의 Create branch here 버튼으로 worktree를 branch로 전환합니다.
이후 변경 사항을 commit하고, branch를 remote repository에 push하고, GitHub에서 pull request를 열 수 있습니다.
스레드 header의 "Open" 버튼으로 IDE를 worktree에 열거나, 통합 터미널을 사용하거나, worktree 디렉터리에서 필요한 다른 작업을 수행할 수 있습니다.
worktree에서 branch를 만들면 local checkout을 포함해 다른 어떤 worktree에서도 그 branch를 checkout할 수 없습니다.
옵션 2: 스레드를 Local로 hand off
스레드를 foreground로 가져오려면 스레드 header에서 Hand off를 클릭하고 Local로 이동합니다.
이 경로는 일반 IDE 창에서 변경 사항을 읽고 싶거나, 기존 개발 서버를 실행하고 싶거나, 매일 사용하는 같은 환경에서 작업을 검증하고 싶을 때 잘 맞습니다.
Codex는 worktree와 local checkout 사이에서 스레드를 안전하게 이동하는 데 필요한 Git 단계를 처리합니다.
각 스레드는 시간이 지나도 같은 연결 worktree를 유지합니다. 나중에 스레드를 다시 worktree로 hand off하면 Codex는 그 스레드를 같은 background 환경으로 돌려보내 중단한 지점에서 이어가게 합니다.
반대 방향도 가능합니다. 이미 Local에서 작업 중이고 foreground를 비우고 싶다면 Hand off로 스레드를 worktree로 이동합니다. 사용자가 로컬에서 다른 일에 집중하는 동안 Codex가 background에서 계속 작업하게 할 때 유용합니다.
Handoff는 Git 작업을 사용하므로 .gitignore에 포함된 파일은 스레드와 함께 이동하지 않습니다.
고급 세부 사항
Codex 관리 worktree와 영구 worktree
기본적으로 스레드는 Codex가 관리하는 worktree를 사용합니다. 이는 가볍고 disposable하게 느껴지도록 설계되었습니다. Codex 관리 worktree는 일반적으로 한 스레드 전용이며, 나중에 다시 handoff하면 Codex는 그 스레드를 같은 worktree로 돌려보냅니다.
오래 유지되는 환경이 필요하면 사이드바의 프로젝트 three-dot 메뉴에서 permanent worktree를 만듭니다. 이는 새 permanent worktree를 별도 프로젝트로 만듭니다. permanent worktree는 자동 삭제되지 않으며, 같은 worktree에서 여러 스레드를 시작할 수 있습니다.
Codex가 worktree를 관리하는 방식
Codex는 $CODEX_HOME/worktrees에 worktree를 만듭니다. 시작 commit은 스레드를 시작할 때 선택한 branch의 HEAD commit입니다. local change가 있는 branch를 선택했다면 uncommitted change도 worktree에 적용됩니다. worktree는 branch로 checkout되지 않으며 detached HEAD 상태가 됩니다. 이렇게 하면 Codex가 branch를 어지럽히지 않고 여러 worktree를 만들 수 있습니다.
branch 제한
Codex가 worktree에서 작업을 끝낸 뒤 Create branch here로 feature/a branch를 만들었다고 가정합니다. 이제 local checkout에서 이를 시험하려고 같은 branch를 checkout하면 다음 오류가 발생합니다.
fatal: 'feature/a' is already used by worktree at '{WORKTREE_PATH}'
이를 해결하려면 worktree에서 feature/a 대신 다른 branch를 checkout해야 합니다.
branch를 local에서 checkout할 계획이라면 같은 branch를 두 위치에서 동시에 checkout하려 하지 말고 Handoff로 스레드를 Local로 이동합니다.
이 제한은 Git branch가 refs/heads/{name}이라는 단일 mutable reference이며, 의미상 "working tree의 현재 checkout 상태"를 나타내기 때문에 존재합니다. 여러 worktree가 같은 branch를 동시에 checkout하게 허용하면 어떤 worktree의 commit, reset, rebase, merge가 branch reference를 갱신해야 하는지 모호해지고 race condition이 생길 수 있습니다. Git은 branch당 worktree 하나 규칙을 강제해 각 branch에 하나의 authoritative working copy를 보장하면서도 detached HEAD나 별도 branch로 같은 commit을 안전하게 참조할 수 있게 합니다.
worktree 정리
Worktree는 디스크 공간을 많이 사용할 수 있습니다. 각 worktree에는 저장소 파일, 의존성, build cache 등이 따로 있습니다. 따라서 Codex 앱은 worktree 수를 합리적인 한도 안에 유지하려고 합니다.
기본적으로 Codex는 가장 최근의 Codex 관리 worktree 15개를 유지합니다. 직접 디스크 사용량을 관리하고 싶다면 설정에서 이 제한을 바꾸거나 자동 삭제를 끌 수 있습니다.
Codex는 여전히 중요한 worktree를 삭제하지 않으려 합니다. Codex 관리 worktree는 다음 경우 자동 삭제되지 않습니다.
- pinned conversation이 연결되어 있습니다.
- 스레드가 아직 진행 중입니다.
- worktree가 permanent worktree입니다.
Codex 관리 worktree는 다음 경우 자동 삭제됩니다.
- 연결된 스레드를 archive합니다.
- 구성된 제한 안에 머물기 위해 Codex가 오래된 worktree를 삭제해야 합니다.
Codex 관리 worktree를 삭제하기 전에 Codex는 그 위의 작업 snapshot을 저장합니다. worktree가 삭제된 뒤 대화를 열면 복원 옵션이 표시됩니다.
자주 묻는 질문
worktree가 만들어지는 위치를 제어할 수 있나요?
현재는 할 수 없습니다. Codex는 일관되게 관리하기 위해 $CODEX_HOME/worktrees 아래에 worktree를 만듭니다.
Local과 Worktree 사이에서 스레드를 이동할 수 있나요?
예. 스레드 header의 Hand off를 사용해 local checkout과 worktree 사이에서 스레드를 이동합니다. Codex는 환경 사이에서 스레드를 안전하게 이동하는 데 필요한 Git 작업을 처리합니다. 나중에 스레드를 worktree로 다시 hand off하면 Codex는 같은 연결 worktree로 돌려보냅니다.
worktree가 삭제되면 스레드는 어떻게 되나요?
기반 worktree 디렉터리가 삭제되어도 스레드는 history에 남을 수 있습니다. Codex 관리 worktree의 경우 Codex는 삭제 전에 snapshot을 저장하고, 연결된 스레드를 다시 열면 복원 옵션을 제공합니다. Permanent worktree는 해당 스레드를 archive해도 자동 삭제되지 않습니다.