Công cụ AI Coding

Git Worktree Với Claude Code: Chạy Nhiều Session Song Song, Không Xung Đột

Aug 19, 202618 phút đọc

Git worktree là một thư mục làm việc riêng, dùng chung lịch sử và remote với repo chính nhưng có file và branch của riêng nó - nên hai session Claude Code không bao giờ đụng file của nhau. Lệnh duy nhất cần nhớ: claude --worktree feature-auth (hoặc -w) tạo một checkout cô lập và mở session ngay trong đó, trên một branch mới, chỉ trong vài giây. Bài này đi theo đúng toolchain gốc của Claude Code (--worktree, .worktreeinclude, EnterWorktree - không phải git worktree add thô), một workflow 3-tính-năng-song-song thật, cách quản lý port/process mà nhiều bài khác bỏ qua, và khi nào worktree KHÔNG phải công cụ đúng - nó cô lập file, không điều phối công việc.

- Số version, hành vi flag, và bảng so sánh worktrees-vs-agents bên dưới đã đối chiếu trực tiếp với tài liệu chính thức tại thời điểm viết (20/08/2026); hành vi worktree của Claude Code đã đổi vài lần trong năm nay, hãy kiểm tra lại trước khi phụ thuộc.

Vấn đề: vì sao một thư mục làm việc duy nhất phá hỏng các session Claude Code chạy song song

Chạy hai session Claude Code trong cùng một thư mục, sớm muộn gì bạn cũng đụng cùng một bức tường: session A đang sửa dở một file, session B chạm vào đúng file đó, và giờ bạn phải xử lý một xung đột mà chẳng session nào cố ý gây ra. Ba kiểu lỗi cụ thể hay gặp nhất:

  • Chỉnh sửa file đè lên nhau - hai session ghi cùng lúc vào cùng một file, một bên ghi đè mất công của bên kia.
  • Test fail vì lý do chẳng liên quan gì tới thay đổi của bạn - một lần cài dependency, một migration làm dở, hoặc một file rác từ task của session kia.
  • Nhầm branch, mất dấu ngữ cảnh - bạn không còn nhớ session nào đụng vào đâu, và git status không còn nghĩa lý gì nữa.

Tài liệu chính thức của Claude Code cũng đóng khung vấn đề y hệt vậy: chạy mỗi session trong worktree riêng để "một session build tính năng trong khi session còn lại fix bug", mà không session nào đụng vào file của session kia. Nếu bạn còn chưa quen Claude Code nói chung, bắt đầu từ Claude Code là gì trước; bài này giả định bạn đã dùng Claude Code hằng ngày và vừa mới đụng đúng bức tường này.

Bắt đầu nhanh: mở Claude trong một worktree

Thêm --worktree (hoặc flag ngắn -w) kèm một tên để tạo worktree cô lập và mở session ngay trong đó, gói gọn trong một lệnh:

claude --worktree feature-auth

Mặc định Claude Code tạo worktree tại .claude/worktrees/feature-auth/ ngay trong repo, trên một branch mới tên worktree-feature-auth. Mở terminal thứ hai, chạy đúng lệnh với tên khác, bạn có ngay một session thứ hai hoàn toàn cô lập, cùng trỏ vào lịch sử của đúng repo đó:

claude --worktree fix-checkout-race

Bỏ trống tên, Claude tự sinh một cái - kiểu bright-running-fox - ổn cho session dùng-rồi-bỏ, nhưng khó phân biệt ba terminal về sau, nên đặt tên cho bất cứ thứ gì bạn định giữ lại.

Hai việc set up một lần rồi quên:

  • Thêm .claude/worktrees/ vào .gitignore, để nội dung worktree không hiện thành untracked file trong checkout chính.
  • Session tương tác cần workspace trust: nếu chưa từng chạy Claude trong repo này, chạy claude một lần ở checkout chính để chấp nhận hộp thoại trust, hoặc --worktree sẽ thoát kèm lỗi nhắc bạn làm vậy. Chạy non-interactive với -p thì bỏ qua bước check này hoàn toàn, nên claude -p --worktree <tên> chạy thẳng không hỏi - hữu ích cho các lần chạy kiểu script/CI.

Worktree là một checkout mới tinh, không phải bản clone có sẵn setup local của bạn - cài dependency (hoặc nhờ Claude cài) trước khi bắt tay vào việc. Phần sau nói về cách mang .env sang tự động.

Worktrees vs subagents vs agent view vs agent teams: bạn thực sự cần cái nào?

Worktree chỉ giải quyết đúng một vấn đề: nhiều session song song đụng cùng file. Nó không quyết định ai điều phối công việc hay các worker có nói chuyện với nhau không - cho việc đó, chính tài liệu Claude Code đưa ra một khung quyết định rất đáng dùng ở trang so sánh agents (lấy 20/08/2026), xoay quanh ba câu hỏi: ai điều phối công việc, các worker có cần nói chuyện với nhau không, và các task có đụng cùng file không. Worktree chỉ trả lời được câu cuối.

Cách tiếp cậnBạn được gìDùng khi nào
SubagentsWorker được giao việc bên trong một session, chạy trong context riêng và trả về bản tóm tắtMột task phụ sẽ làm tràn ngập conversation chính bằng kết quả bạn không cần tham chiếu lại
Agent view (claude agents)Một màn hình để dispatch và theo dõi session chạy nền - research previewNhiều task độc lập bạn muốn giao rồi quay lại kiểm tra sau
Agent teamsNhiều session phối hợp, dùng chung task list và nhắn tin qua lại, có một lead quản lý - thử nghiệm, mặc định tắtBạn muốn Claude tự chia nhỏ dự án, phân việc, và giữ các worker đồng bộ
Dynamic workflowsMột script chạy nhiều subagent và đối chiếu chéo kết quảViệc quá lớn để điều phối trong một lượt, hoặc kết quả cần được xác minh chéo
WorktreesMỗi session có checkout git riêng, nên sửa file không bao giờ đụng nhauBạn tự chạy các session và các task đụng cùng file

Thực tế bạn kết hợp chúng: agent view tự động đưa mỗi session được dispatch vào worktree riêng, và một subagent bạn spawn ra cũng có thể có worktree riêng (phần sau). Agent teams là ngoại lệ đáng lưu ý - teammate mặc định KHÔNG được cô lập trong worktree, nên bạn phải tự chia file cho từng người. Nếu bạn đang điều phối nhiều subagent trong một session, xem orchestrate nhiều subagents; muốn tìm hiểu setup multi-session còn đang thử nghiệm, xem agent teams của Claude Code.

Mang theo env và secrets vào mọi worktree mới (.worktreeinclude)

Worktree là checkout mới tinh: các file bị gitignore như .env hay .env.local đơn giản là không có ở đó, vì git chưa từng track chúng. Thêm file .worktreeinclude vào gốc project để tự động copy chúng vào mỗi lần Claude tạo worktree. File này dùng cú pháp .gitignore, chỉ copy file vừa khớp pattern vừa đã bị gitignore - file đã track thì không bao giờ bị nhân bản:

.env
.env.local
config/secrets.json

Cơ chế này áp dụng cho mọi worktree Claude Code tạo qua git: session bạn mở bằng --worktree, worktree của subagent (phần sau), và các session song song trong desktop app. Một ngoại lệ đáng nhớ: nếu bạn thay cơ chế tạo worktree bằng WorktreeCreate hook cho VCS không phải git, .worktreeinclude bị bỏ qua hoàn toàn, bạn phải tự copy file ngay trong hook script - trường hợp hiếm gặp trừ khi bạn dùng SVN hay Perforce.

Một workflow thật: 3 tính năng song song trong 3 worktree

Đây là phần nhiều bài hướng dẫn khác bỏ qua hoặc viết cho có: điều gì thực sự xảy ra khi bạn chạy ba session Claude Code cùng lúc, dùng đúng toolchain gốc thay vì git worktree add thô. Mình đã chạy đúng setup này - ba terminal, ba worktree, giá trị PORT riêng cho từng cái - trước khi viết phần này, nên các bước dưới đây là thứ thực sự xảy ra, không phải giả định.

Giả sử bạn đang làm cùng lúc: redesign trang giá, fix race condition ở checkout, và refactor API client. Ba terminal (hoặc ba pane tmux), ba lệnh:

claude --worktree pricing-page
claude --worktree fix-checkout-race
claude --worktree refactor-api-client

Mỗi cái rơi vào đúng thư mục .claude/worktrees/<tên>/ riêng, trên branch worktree-<tên> riêng, dùng chung lịch sử repo. Các bước cho cả vòng lặp:

  1. Set up môi trường cho từng worktree. Nếu đã có .worktreeinclude (phần trước), .env đã tự copy sẵn. Đặt PORT riêng cho từng worktree trong .env đó - PORT=3001 cho pricing-page, 3002 cho fix-checkout-race, 3003 cho refactor-api-client - để ba dev server chạy cùng lúc mà không tranh nhau một port.
  2. Đặt tên tab terminal/pane tmux trùng tên worktree. Ba terminal không nhãn cùng in ra output "claude" là cách chắc chắn nhất để bạn lẫn lộn session nào là session nào sau giờ thứ hai.
  3. Để mỗi session làm việc độc lập. Giao instruction riêng cho từng cái và để nó chạy; bạn không cần canh cả ba cùng lúc.
  4. Kiểm tra trạng thái cả ba từ một chỗ. Mở claude agents để xem view các session đã dispatch, hoặc chạy /tasks trong bất kỳ session nào để xem cái gì đang chạy nền - khỏi phải chuyển qua lại ba terminal chỉ để check tiến độ.
  5. Merge cái xong sạch trước. Worktree nào xong sạch nhất (test pass, không còn sửa dở) thì merge và dọn trước - đừng để một session chậm chặn hai session đã sẵn sàng.
  6. Giữ lại cái đang làm dở khi thoát. Thoát một session có tên mà còn việc chưa commit, Claude sẽ hỏi bạn giữ hay xóa worktree; chọn giữ, và lần sau nó vẫn nằm y nguyên chỗ bạn để lại.

Lần đầu thử cái này mà chưa cô lập port, điều thực sự xảy ra: hai trong ba dev server từ chối khởi động vì tranh nhau localhost:3000, và mình mất hai mươi phút tưởng là bug code trước khi nhận ra chỉ là đụng port. Đó là toàn bộ lý do phần sau tồn tại.

Một chi tiết đáng biết nữa của toolchain gốc: giữa chừng session, bạn cũng có thể bảo Claude "làm việc trong một worktree" thay vì mở từ command line, và nó tạo ngay một worktree bằng tool EnterWorktree - tiện khi bạn nhận ra cần cô lập giữa chừng conversation thay vì tính trước từ đầu.

Cô lập subagent trong worktree riêng

Worktree không chỉ dành cho session bạn tự mở tay. Một subagent mà Claude spawn ra trong session cũng có thể có worktree riêng, để việc nó sửa không đụng vào việc của bạn hay của subagent khác. Hai cách kích hoạt: bảo Claude "dùng worktree cho các agent của bạn" giữa session, hoặc set cố định cho một custom subagent cụ thể bằng cách thêm isolation: worktree vào frontmatter:

---
name: refactorer
description: Applies mechanical refactors across many files
isolation: worktree
---

Apply the requested refactor across every affected file, then run the
tests and report the results.

Claude Code tự xóa worktree tạm của subagent ngay khi nó xong việc mà không để lại thay đổi gì; nếu có để lại thay đổi, worktree vẫn nằm trên đĩa cho tới khi lượt dọn dẹp định kỳ xóa được nó mà không mất việc (phần sau). Trong lúc subagent đang chạy, Claude Code giữ git worktree lock trên nó để một lượt cleanup chạy song song không thể rút nó ra giữa chừng.

Worktree của subagent mặc định branch từ cùng gốc với session --worktree - branch mặc định của repo, trừ khi bạn set worktree.baseRef thành "head" để agent cô lập có thể thao tác trên việc đang làm dở của bạn thay vì bản sạch. Muốn hiểu toàn cảnh dispatch và điều phối nhiều subagent cùng lúc, xem orchestrate nhiều subagents trong Claude Code.

Quản lý port, process, dev server giữa các worktree

Đây là phần nhiều bài khác bỏ qua hoặc chỉ nhắc một câu cho có, và cũng là cách phổ biến nhất một setup nhiều-worktree ngốn mất buổi chiều của bạn: mọi thứ trông như hỏng, mà thực ra chỉ là đụng port hay đụng database, không phải bug code. Ba thứ mỗi worktree cần có bản riêng:

Tài nguyênVì sao đụng nhauCách xử lý
Port dev serverMọi worktree đều chạy cùng npm run dev / next dev trên cùng port mặc địnhOverride PORT riêng cho từng worktree qua .env trong .worktreeinclude (xem phần workflow ở trên)
Trạng thái databaseHai session cùng ghi vào một file SQLite hoặc một schema Postgres sẽ giẫm lên nhau giữa lúc testMột file SQLite riêng cho từng worktree, một database/schema Postgres riêng, hoặc dịch vụ database-branching nếu stack của bạn có - chọn theo hạ tầng của bạn, không cần gắn với một vendor cụ thể
Danh tính terminalBa pane cùng in output Claude Code trông giống hệt nhau sau vài phút đầuĐặt tên mỗi tab/pane tmux trùng tên worktree, đặt ngay lúc mở session

Không có gì cao siêu ở đây - đó là kiểu vệ sinh bạn vẫn cần khi chạy cùng lúc ba dev server local bất kỳ. Điểm khác khi dùng worktree là bạn dễ quên, vì bản thân worktree đã cảm giác "cô lập" dù port mặc định của dev server và file database của bạn không tự động cô lập theo. Set PORT override và tách DB trước khi mở session, đừng đợi tới lúc dev server thứ hai từ chối khởi động.

Dọn dẹp: đừng để worktree chất đống

Điều xảy ra khi thoát phụ thuộc vào việc session có tên hay không, và worktree có sạch hay không:

  • Session không tên, worktree sạch: Claude tự xóa worktree và branch của nó ngay khi bạn thoát.
  • Session có tên, hoặc worktree còn việc dang dở: Claude hỏi bạn giữ hay xóa. Giữ thì giữ nguyên thư mục và branch cho lần sau; xóa thì xóa cả worktree, branch, và mọi thứ trong đó.
  • Chạy non-interactive với -p: không có prompt thoát nào cả, nên không gì được dọn tự động. Lock mà Claude Code đặt lên worktree lúc tạo vẫn nằm nguyên cho tới khi một session sau đó chạy lượt dọn định kỳ và giải phóng nó.

Lượt dọn định kỳ đó xóa các worktree Claude tạo cho subagent và session chạy nền một khi chúng cũ hơn cửa sổ giữ lại cleanupPeriodDays bạn đã cấu hình (trong settings) - nó bỏ qua bất cứ worktree nào còn file thay đổi, file chưa track, hoặc commit chưa push, và không bao giờ xóa worktree bạn tự tạo bằng --worktree.

Lệnh thủ công khi bạn muốn tự kiểm soát:

git worktree list
git worktree remove <path>
git worktree remove --force <path>
git worktree unlock <path>

Nếu git worktree remove từ chối vì worktree đang bị lock, chạy git worktree unlock trước rồi remove.

Những lỗi hay gặp

  • Mở Claude từ bên trong worktree thay vì checkout chính. Claude Code vẫn re-enter được worktree nó tự tạo dưới .claude/worktrees/ dù bạn mở từ bên trong, nhưng một worktree bạn tự tạo bằng git worktree add thô (nằm ngoài thư mục đó) có thể từ chối resume nếu bạn mở từ một thư mục con của nó - hãy mở những cái đó từ checkout chính.
  • Quên gitignore .claude/worktrees/. Bỏ qua bước này, nội dung của mọi worktree sẽ hiện thành untracked file làm rối git status ở checkout chính.
  • Bất ngờ với prompt xác nhận của EnterWorktree. Từ v2.1.206, khi Claude thử vào một đường dẫn worktree nằm ngoài .claude/worktrees/, nó hỏi xác nhận trước, vì việc chuyển này trao luôn quyền ghi và config dự án như CLAUDE.md cho vị trí đó. Không có permission rule đã lưu hay "don't ask again" nào chặn được prompt này - chỉ chế độ bypassPermissions mới bỏ qua được.
  • Bỏ qua cô lập port/DB. Đã nói ở trên nhưng đáng nhắc lại: đây là nguồn gốc số một của kiểu lỗi "test fail vô cớ" trong một setup nhiều worktree.
  • Windows: xóa worktree không xóa file nằm ngoài nó - gần như vậy. Nếu một thư mục bên trong worktree thực chất là NTFS junction hay symlink thư mục, Claude Code chỉ xóa cái link và giữ nguyên thư mục thật nó trỏ tới. Hành vi này đúng tính tới v2.1.205; kiểm tra lại nếu bạn đọc bài này lâu sau, vì phần lõi worktree đã có vài lần sửa trong năm nay.

Lỡ sửa nhầm worktree, hay cần lùi lại một thay đổi agent làm giữa session? Xem hoàn tác thay đổi an toàn trong Claude Code - hợp tự nhiên với việc thử nghiệm trong một worktree cô lập ngay từ đầu.

AgentKit nằm ở đâu trong bức tranh này (thẳng thắn, nhắc một lần)

Nói thẳng: worktree, .worktreeinclude, và EnterWorktree đều là tính năng native của Claude Code, không tốn thêm phí gì ngoài plan bạn đang trả. AgentKit là một bộ kit riêng, trả phí (agentkit.best, CLI ak) chạy bên trong Claude Code sau khi cài bằng ak kit init engineer --target claude-code. Nó không đổi cách worktree hoạt động - một session chạy lệnh AgentKit như ak:cook hoạt động y hệt bất kỳ session Claude Code nào khác bên trong worktree, vẫn checkout cô lập như thường.

Một điều đáng tự kiểm tra thay vì tin suông: tài liệu Claude Code xác nhận plugin cài ở project scope từ checkout chính tự động load vào mọi worktree mới của repo đó mà không cần cài lại (tính từ v2.1.200). Còn việc install path của AgentKit có đăng ký qua đúng cơ chế plugin đó hay không, hay ghi file theo cách khác, mình chưa tự kiểm chứng độc lập - đáng để xem tài liệu riêng của AgentKit trước khi mặc định rằng kit của bạn sẽ tự động theo sang worktree mới giống hệt một plugin marketplace.

Nếu bạn đang chạy vòng lặp ngày-plan/đêm-execute hay làm song song nhiều tính năng và muốn có sẵn các gate của AgentKit trong đó, review AgentKit đầy đủ nói rõ phần nào đã được xác nhận.

Câu hỏi thường gặp (FAQ)

Có cần worktree để chạy Claude Code song song không, hay mở hai terminal trong cùng thư mục là đủ?

Hai terminal trong cùng một thư mục vẫn dùng chung một working directory, nên cả hai session sửa cùng file và bạn gặp đúng những xung đột bài này mô tả. Worktree cho mỗi session một checkout riêng của cùng lịch sử repo, nên hai (hay ba) session mới thực sự chạy song song mà không đụng file của nhau.

Desktop app có tự tạo worktree không?

Có. Trong Claude Code desktop app, mỗi session song song mới đều tự có worktree riêng, khỏi cần tự truyền --worktree.

Hai session Claude có thể dùng chung một worktree không?

Không an toàn cho việc chạy song song - worktree được thiết kế cho checkout cô lập của một session tại một thời điểm. Nếu muốn hai session thấy trạng thái của nhau hoặc trao đổi thông tin, dùng cross-session messaging hoặc xem /tasks và claude agents, đừng dùng chung một worktree.

File .env của mình ra sao trong worktree mới?

Không có gì cả - worktree là checkout mới tinh, nên file bị gitignore như .env không tự copy sang. Thêm file .worktreeinclude (cú pháp gitignore) vào gốc project, Claude Code sẽ tự copy các file khớp pattern và đã bị gitignore vào mọi worktree mới.

Làm sao để worktree không chất đống trên ổ đĩa?

Session có tên và worktree còn việc chưa commit sẽ hỏi bạn giữ hay xóa khi thoát; session không tên mà sạch thì tự dọn. Một lượt dọn định kỳ cũng xóa worktree cũ của subagent/session nền dựa theo setting cleanupPeriodDays. Muốn tự kiểm soát, chạy git worktree list và git worktree remove [--force].

Worktree có dùng được với SVN/Perforce/repo không phải git không?

Không theo luồng mặc định - cơ chế cô lập worktree dùng git làm nền. Với SVN, Perforce, Mercurial, hay VCS khác, bạn cấu hình hook WorktreeCreate/WorktreeRemove để thay thế logic git bằng logic riêng; lưu ý .worktreeinclude không được xử lý trên nhánh này, nên bạn phải tự copy file config ngay trong hook script.

Kết luận

Worktree giải quyết tốt đúng một vấn đề: các session Claude Code chạy song song mà không giẫm lên file của nhau. Chúng không tự điều phối công việc - ghép với subagent, agent view, hay agent teams cho phần còn lại, dùng khung quyết định ở trên thay vì đoán mò. Bắt đầu bằng một worktree thêm cho task phụ tiếp theo trước khi scale lên ba tính năng song song; làm đúng .worktreeinclude và cô lập port từ sớm, phần dọn dẹp gần như tự lo được.

Muốn có sẵn bộ gate chất lượng cho vòng lặp nhiều-worktree song song? Engineer Kit của AgentKit đóng gói ak:cook, ak:code-review, và ak:ship cho cả Claude Code và Codex, để mỗi session worktree chạy cùng một gate review thay vì bạn tự ráp cho từng branch.

Xem AgentKit Engineer Kit, giảm 20% còn $79.20 →

J

Jasmine

Tác giả · Jasmine Daily

Người viết nên Jasmine Daily - ghi lại những suy nghĩ, trải nghiệm và những khoảnh khắc đời thường. Thật lòng, không vội vàng, không hoàn hảo.

Jasmine Daily

Vẫn còn nhiều điều đang chờ được đọc.

Nếu bài viết này chạm đến bạn, hãy ghé xem thêm vài trang khác trong cuốn nhật ký này.

Đọc tiếp

Bài viết liên quan