Một buổi deploy lớn luôn có nhiều thứ xảy ra cùng lúc. Main session đang tail container log. Bạn đang edit .env.production để chuẩn bị restart. Có một script đang được scp lên server. Container state đang được poll.
Rồi bạn phát hiện một Dockerfile có typo. Một compose file thiếu env var. Nhỏ thôi, fix một lúc xong. Nhưng để fix, bạn phải checkout sang branch hotfix.
Và checkout sẽ reset working tree. Log tail mất, .env.production đang edit dở reset về HEAD, script scp đang xếp hàng bị orphan. Phải mất 15-30 phút để recover toàn bộ về trạng thái trước.
Bài này giải thích tại sao đây là thời điểm đúng để dùng worktree agent, và cho thấy chính xác cách flow đó hoạt động.
Bức tranh trước khi có hotfix
Hãy hình dung buổi deploy một service production. Main session của bạn đang:
Main session (branch: main)
├── terminal tab 1: tail -f /var/log/container/service-a.log
├── terminal tab 2: edit .env.production <-- đang sửa dở
├── terminal tab 3: scp -i key tmp-fix.sh user@prod-server:/tmp/
└── terminal tab 4: watch -n 3 "docker ps --filter name=service-a"
Không có gì trong số này được commit. Đây là scratch state, ephemeral, sống trong working tree và trong terminal process. Không thể “save and restore” kiểu git stash đơn thuần vì git stash không stash được log tail hay scp process.
Bạn phát hiện trong Dockerfile:
# BEFORE (typo)
COPY srcc/ /app/src/
# SHOULD BE
COPY src/ /app/src/
Nhỏ. Một ký tự. Nhưng fix nó đúng cách yêu cầu một commit trên branch riêng, CI chạy, PR review, merge.
Option A và option B: tại sao cả hai đều sai
Option A: fix trực tiếp trong main session. Bạn git checkout -b hotfix/dockerfile-typo, sửa, commit, push, PR. Vấn đề: git checkout reset working tree. .env.production đang edit dở trở về state của HEAD. Script scp mất context. Log tail không biết bạn vừa đổi branch.
Option B: spawn no-isolation agent (không dùng worktree, agent edit trực tiếp trên branch hiện tại). Agent sửa Dockerfile trên branch main. Không có branch riêng, không có PR, không có CI gate. Không phù hợp khi code này cần review trước khi deploy.
Cả hai option đều phá scratch state hoặc bỏ qua quy trình review.
Option C: worktree agent
Worktree agent giải quyết cả hai vấn đề cùng lúc. Về cơ chế worktree, xem bài 17. Về các spawning pattern, xem bài 16.
Tóm tắt nhanh: khi spawn agent với isolation: "worktree", binary tạo một git worktree riêng (thư mục riêng, branch riêng) dựa trên HEAD hiện tại của main session. Agent làm việc trong thư mục đó, không đụng đến working tree của main session.
Main session không hề biết agent đang sửa gì, và không bị ảnh hưởng gì.
Main session Worktree agent
branch: main branch: worktree/dockerfile-fix
working-tree: .env.production working-tree: riêng, độc lập
log-tail: running không liên quan
scp: running không liên quan
│ │
│ │ edit Dockerfile
│ │ git add, commit
│ │ git push
│ │ gh pr create
│ ▼
│ PR #42 opened
│
▼ (khi sẵn sàng)
gh pr merge 42 --squash
git pull --ff-only origin main
Main session vẫn ở branch main, scratch state nguyên vẹn.
Cách spawn trong thực tế
Từ main session, bạn spawn agent theo dạng này:
Spawn agent với isolation: worktree
Task: fix Dockerfile typo trong file Dockerfile ở root project
Cụ thể: dòng "COPY srcc/ /app/src/" phải sửa thành "COPY src/ /app/src/"
Target branch để PR vào: main
Sau khi fix: commit, push, mở PR về main. Không merge, không delete branch.
Agent nhận task, binary tạo worktree mới, agent làm việc trong đó. Bạn quay lại main session và tiếp tục monitor production.
Hai hotfix song song
Deploy lớn thường có nhiều vấn đề nhỏ xuất hiện cùng lúc. Nếu ngoài Dockerfile typo còn có một compose file thiếu env var, bạn có thể spawn hai worktree agent song song:
Agent A (worktree/dockerfile-fix):
Fix: COPY srcc/ -> COPY src/ trong Dockerfile
Agent B (worktree/compose-env-fix):
Fix: thêm DATABASE_URL vào docker-compose.yml service section
Hai agent chạy song song, hai worktree độc lập, hai PR riêng. Main session không bị block bởi bất kỳ agent nào.
Main session (monitor prod)
├── Agent A --> PR #42: fix Dockerfile typo
└── Agent B --> PR #43: add DATABASE_URL to compose
Khi cả hai agent báo xong, bạn merge theo thứ tự:
gh pr merge 42 --squash
git pull --ff-only origin main
gh pr merge 43 --squash
git pull --ff-only origin main
Main session vẫn ở branch main xuyên suốt. Mỗi git pull --ff-only chỉ bring commit mới vào, không switch branch, không reset working tree.
Integration: merge từ main session mà không switch branch
Đây là điểm quan trọng nhất của pattern này. Khi merge, bạn không bao giờ git checkout sang worktree branch trong main session.
Đúng:
# Từ main, merge qua cloud PR
gh pr merge 42 --squash
git pull --ff-only origin main # bring the squashed commit into main
Sai:
# KHÔNG làm thế này
git checkout worktree/dockerfile-fix
git log # explore agent's work
git checkout main
git merge worktree/dockerfile-fix
Lý do: ngay khi bạn git checkout worktree/dockerfile-fix trong main session, working tree reset theo branch đó. .env.production đang edit của bạn bị overwrite bởi version ở HEAD của branch kia. Đây chính xác là vấn đề bạn đang cố tránh.
Review agent’s work trước khi merge
Bạn vẫn review được mà không cần switch branch. Hai cách:
1. Xem PR diff trên GitHub:
gh pr view 42 --web # mở browser, xem diff trực tiếp
2. Fetch và diff locally mà không checkout:
git fetch origin worktree/dockerfile-fix
git diff main...origin/worktree/dockerfile-fix
git diff main...origin/worktree/dockerfile-fix so sánh diff mà không thay đổi HEAD hay working tree của main session. Xem xong, nếu ổn:
gh pr merge 42 --squash
git pull --ff-only origin main
Bài học từ một buổi deploy
Incident pattern phổ biến trông như thế này: một deploy wave lớn, main session đang monitor production với nhiều scratch state đang chạy. Phát hiện hai vấn đề cùng lúc: một Dockerfile nhỏ cần sửa và một compose file thiếu biến.
Thay vì dùng worktree agent, main session checkout hai lần. Mỗi lần checkout reset working tree, .env.production đang edit bị mất, script scp bị orphan. Hai lần như vậy, cộng lại mất gần 30 phút chỉ để recover về trạng thái trước, trước khi thực sự bắt đầu debug vấn đề thật.
Worktree agent là pattern đúng. Main session delegate cả hai fix cho hai agent song song, tiếp tục monitor, merge khi xong. Tổng thời gian overhead: khoảng 5 phút, chủ yếu là thời gian CI chạy.
Anti-pattern cần ghi nhớ
| Pattern | Vấn đề |
|---|---|
git checkout trong main session | Reset working tree, mất scratch state |
| No-isolation agent sửa trên main branch | Không có PR, không có CI gate, không có review |
Merge trực tiếp từ main session bằng git merge worktree/... | Không có audit trail, bypass CI/CD |
Spawn agent dontAsk / bypassPermissions | Cực kỳ nguy hiểm, không bao giờ làm |
Khi nào dùng worktree agent vs. khi nào không cần
Worktree agent có overhead: tạo worktree, CI chạy, PR review. Với hotfix một dòng trong buổi deploy khẩn, overhead đó xứng đáng vì bảo vệ scratch state của main session và đảm bảo review gate trước khi code vào main.
Nhưng không phải lúc nào cũng cần. Nếu main session đang rảnh (không có scratch state nào đáng lo), chỉ có một file nhỏ cần sửa, không cần PR, thì fix trực tiếp trong main session là ổn (option A đúng trong điều kiện đó).
Quyết định là: main session đang giữ scratch state không thể recover dễ không? Nếu có, dùng worktree agent. Nếu không, checkout thẳng là fine.
Có scratch state quan trọng?
├── Có --> worktree agent
└── Không
├── Cần PR/CI gate?
│ ├── Có --> worktree agent
│ └── Không --> fix trực tiếp trong main session
Tóm tắt và bài tiếp theo
- Khi main session đang giữ scratch state (log tail, file đang edit, process đang chạy), bất kỳ
git checkoutnào cũng là rủi ro. Worktree agent tránh hoàn toàn vấn đề này. - Spawn worktree agent với task rõ ràng, agent tự tạo branch riêng, commit, push, mở PR. Main session không bị block và không bị ảnh hưởng.
- Hai hotfix song song: hai worktree agent, hai PR, merge theo thứ tự từ main session bằng
gh pr mergevàgit pull --ff-only. - Không bao giờ
git checkoutsang worktree branch trong main session. Xem diff quagh pr view --webhoặcgit diff main...origin/branch.
Bài 22 sẽ đi sang một use case khác của worktree nhưng ở cấp config: branch-per-machine, cách đồng bộ ~/.claude/ giữa các máy mà không conflict state của từng máy.
Liên quan: skill nf-agents handle case workflow này qua solo mode (single agent + worktree, không cần team registry). Pre-flight check cũng catch case bạn quên WorktreeCreate hook trước khi spawn.
Bài thuộc series Claude Code từ zero. Series plan tại bài giới thiệu.