Bài stash giải bài toán "đổi việc gấp" bằng cách cất tạm. Nhưng có tình huống cần mạnh hơn: bạn muốn làm hai nhánh cùng lúc thật sự — đang code tính năng ở nhánh A, đồng thời cần build và chạy nhánh B để so, hay review một PR trong khi vẫn giữ nguyên công việc dở của mình. Stash thì phải chuyển qua chuyển lại (mất ngữ cảnh); clone lại kho thì tốn dung lượng và tách rời khỏi remote/stash gốc. git worktree giải đúng chỗ này: một kho .git dùng chung, nhiều thư mục làm việc, mỗi thư mục ở một nhánh khác nhau. Đo thật bằng git 2.39.
Một .git, nhiều working tree
Bình thường một kho Git có một thư mục .git và một working tree. git worktree add tạo thêm working tree — một thư mục riêng, ở một nhánh riêng — nhưng dùng chung cùng .git (object, ref, config, remote, stash đều chung).
git worktree add ../wt-B tinh-nang # tạo cây mới ở nhánh tinh-nang
git worktree list # liệt kê các cây + nhánh
git worktree remove ../wt-B # gỡ cây khi xong
git worktree prune # dọn cây đã xóa tay

Hình 1: git worktree cho một .git dùng chung nhưng nhiều thư mục làm việc, mỗi cái ở một nhánh. Nhẹ hơn clone (không nhân đôi lịch sử), giữ chung remote/stash. Quy tắc: không checkout cùng một nhánh ở hai cây.
Đo thật: hai cây, hai nhánh, làm việc song song

Hình 2: worktree list cho thấy hai cây main-repo [master] và wt-tinhnang [tinh-nang]. Mỗi cây làm việc độc lập; commit 145c503 feat tạo ở cây tinh-nang được thấy ngay từ main-repo (git log tinh-nang). Thử checkout master ở cây thứ hai → fatal: 'master' is already checked out.
Kết quả làm rõ mọi thứ:
- Nhiều cây một lệnh:
git worktree add ../wt-tinhnang tinh-nangtạo thư mụcwt-tinhnangđã checkout sẵn nhánhtinh-nang.git worktree listliệt kê cả hai cây kèm nhánh của mỗi cây. - Làm việc song song thật: sửa
app.txtởmain-repo(master) và commitfeature.txtởwt-tinhnang(tinh-nang) — hai cây độc lập, không đụng nhau, không cần stash hay đổi nhánh qua lại. Bạn có thể mở hai cửa sổ terminal / hai cửa sổ IDE trên hai thư mục. - Chung một
.git: commit145c503 featvừa tạo ở câytinh-nangđược thấy ngay từmain-repo(git log tinh-nang) — vì object và ref dùng chung, không cần push/pull giữa hai cây. Đây là khác biệt cốt lõi với việc clone hai bản (clone thì phải push/pull để đồng bộ). - Quy tắc một nhánh một cây: thử
git worktree add ../wt-master master→fatal: 'master' is already checked out at 'main-repo'. Git cấm checkout cùng một nhánh ở hai cây cùng lúc, vì hai working tree cùng ghi đè con trỏ nhánh sẽ hỏng. Mỗi nhánh chỉ được một cây "giữ".
Đánh đổi và lưu ý
Worktree lý tưởng cho: build/test song song, review PR, hotfix. Ví dụ: git worktree add ../hotfix main để sửa bug production ở một thư mục riêng, build và deploy, trong khi thư mục chính vẫn giữ nguyên công việc dở — không stash, không mất trạng thái IDE. Hay CI/build một nhánh trong khi bạn code nhánh khác.
Nhớ dọn bằng git worktree remove, đừng xóa thư mục tay. Nếu xóa thư mục worktree bằng rm -rf mà không git worktree remove, Git vẫn giữ metadata "ma" trong .git/worktrees — dọn bằng git worktree prune. Và một worktree có thay đổi chưa commit thì remove bị chặn (dùng --force nếu chắc chắn bỏ).
File không theo dõi và build artifact không chia sẻ. Mỗi cây có working tree riêng, nên node_modules/, file build, cấu hình cục bộ không dùng chung — mỗi cây phải cài/build riêng. Đây vừa là điểm mạnh (cô lập) vừa là chi phí (tốn chỗ cho mỗi cây). Với dự án có bước cài đặt nặng, cân nhắc.
Ba ý mang về
git worktreecho một.gitdùng chung, nhiều thư mục làm việc ở các nhánh khác nhau — đo thật,main-repo [master]vàwt-tinhnang [tinh-nang]làm việc song song độc lập, không cần stash/clone lại.- Chung object/ref nên đồng bộ tức thì: commit ở cây này (
145c503 feat) thấy ngay từ cây kia mà không cần push/pull — nhẹ hơn clone (không nhân đôi lịch sử), giữ chung remote/stash. - Một nhánh chỉ một cây: Git chặn checkout cùng nhánh ở hai cây (
fatal: already checked out); nhớgit worktree remove/pruneđể dọn, và file untracked/build không chia sẻ giữa các cây.
Nguồn
- Git Documentation — git-worktree: https://git-scm.com/docs/git-worktree
- Pro Git / Atlassian — Managing multiple worktrees: https://git-scm.com/book/en/v2
Phần sau ta xử lý một kiểu "repo trong repo" khác — git submodule: nhúng một kho Git vào kho khác, con trỏ commit cố định, và vì sao submodule hay gây rối nếu không hiểu cơ chế.