Muốn chạy nhiều tác tử AI cùng lúc trên một kho mã, mỗi tác tử cần một thư mục làm việc riêng trên một nhánh riêng. Lệnh git worktree làm đúng việc đó: nhiều thư mục, chung một kho, mỗi thư mục một nhánh. Phần khó không nằm ở lệnh mà ở cách chia việc sao cho các tác tử không sửa chồng lên cùng tệp, và ở sức duyệt của chính bạn.
Bài này dành cho người đã quen làm với một tác tử trên nhánh riêng và muốn tăng lên hai ba phiên song song. Bài nói rõ khi nào đáng làm, khi nào không, các lệnh worktree cơ bản (có từ git bản 2.5, các lệnh con như xoá thư mục có ở bản mới hơn), và cách gộp kết quả về theo thứ tự hợp lý.
Khi nào chạy song song là đáng, khi nào chỉ thêm rối
Chạy song song đáng khi bạn có vài việc độc lập, mỗi việc đủ rõ để viết phiếu giao việc chặt, và phần lớn thời gian của một phiên là tác tử tự chạy kiểm thử, tự sửa, không cần bạn trả lời. Ví dụ giả định: một tác tử viết kiểm thử cho mô-đun tính giá, một tác tử cập nhật tài liệu cho phần giao diện lập trình đã đổi, một tác tử sửa các cảnh báo lỗi thời ở thư mục báo cáo. Ba việc ở ba vùng mã khác nhau, không phụ thuộc nhau.
Không đáng khi các việc chạm cùng một vùng mã, khi việc sau cần kết quả việc trước, hoặc khi việc nào cũng cần bạn ngồi trả lời câu hỏi. Khi đó bạn chuyển qua lại giữa các phiên, mỗi phiên chờ bạn một lúc, và cuối cùng chậm hơn làm tuần tự.
Giới hạn thật sự thường không phải là máy hay công cụ, mà là sức duyệt của bạn. Ba tác tử xong việc cùng lúc nghĩa là ba diff đang chờ đọc. Nếu bạn chỉ đọc kỹ được một, hai cái còn lại sẽ bị đọc lướt, và lợi ích của việc chạy song song biến thành rủi ro. Nhiều người thấy hai phiên song song là mức thoải mái; ba là trần với việc nhỏ.
Dựng worktree cho từng tác tử
Giả định kho chính nằm ở thư mục cuahang, nhánh chính là main. Các lệnh chạy từ trong thư mục kho chính.
- Cập nhật nhánh chính: git switch main rồi git pull.
- Tạo thư mục làm việc thứ nhất kèm nhánh mới: git worktree add ../cuahang-kiemthu -b ai/kiem-thu-tinh-gia. Thư mục mới nằm cạnh kho chính, đã ở sẵn trên nhánh mới.
- Tạo thư mục thứ hai: git worktree add ../cuahang-tailieu -b ai/tai-lieu-api.
- Trong mỗi thư mục mới, cài phụ thuộc và tạo tệp cấu hình cục bộ như khi sao chép dự án lần đầu. Những thứ git không theo dõi không tự có trong worktree mới.
- Mở mỗi phiên tác tử trong đúng một thư mục, giao phiếu việc tương ứng.
- Xem danh sách thư mục làm việc bất cứ lúc nào bằng git worktree list.
Một nhánh chỉ được mở ở một worktree tại một thời điểm; git sẽ từ chối nếu bạn cố mở nhánh đang dùng ở thư mục khác. Đây là điều tốt, nó ngăn hai tác tử ghi nhận chồng lên cùng một nhánh. Các worktree dùng chung lịch sử và kho đối tượng, nên lần ghi nhận ở thư mục này thấy được ngay từ thư mục khác qua tên nhánh.
Chia việc sao cho không giẫm chân
Chia theo vùng mã, không chia theo loại việc. Hai tác tử cùng "sửa cảnh báo" ở hai thư mục khác nhau ít xung đột hơn một tác tử "sửa cảnh báo" và một tác tử "viết kiểm thử" cùng một thư mục. Trước khi giao, liệt kê thư mục mỗi phiếu được phép sửa và kiểm không có chỗ chồng.
Cẩn thận với tệp dùng chung. Tệp khai báo phụ thuộc, tệp khoá phiên bản, tệp cấu hình chung, tệp đăng ký tuyến đường hay danh sách mô-đun là nơi xung đột hay xảy ra nhất, vì việc nào cũng muốn thêm một dòng. Ghi trong phiếu: không sửa các tệp này, cần thì dừng hỏi.
Không giao việc đổi tên hay đổi cấu trúc song song với việc khác. Một tác tử đổi tên hàm dùng ở năm mươi chỗ sẽ xung đột với gần như mọi việc khác. Việc kiểu đó làm một mình, gộp xong rồi mới mở các phiên khác.
Đặt tên nhánh và thư mục khớp nhau. Thư mục cuahang-kiemthu đi với nhánh ai/kiem-thu-tinh-gia. Khi có ba cửa sổ mở, bạn nhìn tên thư mục là biết đang ở phiên nào, tránh giao nhầm phiếu.
Những thứ worktree không tách giúp bạn
Worktree chỉ tách mã nguồn. Môi trường chạy thì không, và đây là nguồn lỗi khó hiểu nhất khi chạy song song.
| Tài nguyên dùng chung | Vấn đề | Cách xử lý |
|---|---|---|
| Cổng mạng của máy chủ phát triển | Hai phiên cùng chạy máy chủ thử ở một cổng, phiên sau báo lỗi hoặc kiểm thử gọi nhầm sang phiên kia | Gán mỗi worktree một cổng riêng trong cấu hình cục bộ |
| Cơ sở dữ liệu thử nghiệm | Hai bộ kiểm thử cùng xoá và tạo lại dữ liệu, làm hỏng kết quả của nhau | Mỗi worktree một cơ sở dữ liệu thử riêng, hoặc dùng cơ sở dữ liệu trong bộ nhớ cho kiểm thử |
| Thư mục bộ nhớ đệm, tệp tạm ngoài kho | Ghi đè lẫn nhau nếu đường dẫn cố định | Đặt đường dẫn tương đối theo thư mục dự án |
| Tài nguyên máy: bộ nhớ, CPU | Ba bộ kiểm thử nặng chạy cùng lúc làm máy chậm, kiểm thử có giới hạn thời gian bị đỏ oan | Giới hạn số phiên, hoặc lệch giờ chạy kiểm thử nặng |
| Hạn mức của công cụ AI | Nhiều phiên cùng lúc tiêu hạn mức nhanh hơn | Theo dõi mức sử dụng, ưu tiên phiên quan trọng |
Nếu dự án dùng container để dựng môi trường, việc tách dễ hơn nhiều: mỗi worktree một bộ container với tên dự án riêng. Nếu không, ít nhất hãy viết sẵn một tệp cấu hình cục bộ mẫu có biến cổng và tên cơ sở dữ liệu, để mỗi worktree mới chỉ cần đổi hai giá trị.
Một buổi sáng với hai tác tử: ví dụ giả định
Tám giờ, bạn viết hai phiếu việc: phiếu thứ nhất thêm kiểm thử cho mô-đun tính giá, chỉ được sửa thư mục kiểm thử của mô-đun đó; phiếu thứ hai sửa cảnh báo lỗi thời ở thư mục báo cáo, không đụng tệp khai báo phụ thuộc. Bạn dựng hai worktree, cài phụ thuộc, đổi cổng và tên cơ sở dữ liệu thử ở worktree thứ hai, rồi mở hai phiên. Việc chuẩn bị mất khoảng hai mươi phút, phần lớn là chờ cài phụ thuộc.
Trong lúc hai tác tử chạy, bạn không ngồi nhìn. Bạn làm việc của mình ở kho chính, một việc cần suy nghĩ mà không cần tác tử, chỉ liếc qua khi phiên nào báo cần hỏi. Phiên thứ hai dừng một lần: một cảnh báo chỉ sửa được bằng cách nâng phiên bản thư viện. Bạn trả lời không nâng, bỏ qua cảnh báo đó và ghi lại vào thẻ công việc.
Gần mười giờ, cả hai xong. Bạn duyệt phiên kiểm thử trước vì nó không đổi mã sản phẩm, gộp, rồi cập nhật nhánh báo cáo theo nhánh chính mới và chạy lại kiểm thử ở worktree đó. Một kiểm thử mới của phiên thứ nhất đỏ vì phiên thứ hai đã đổi cách định dạng số trong báo cáo, đúng loại xung đột hành vi không hiện ra ở cấp tệp. Bạn sửa kỳ vọng sau khi xác nhận định dạng mới là đúng, gộp nốt, dọn hai worktree. Hai việc nhỏ xong trong buổi sáng, cùng lúc với việc của bạn.
Duyệt và gộp theo thứ tự
Khi các phiên xong, đừng duyệt theo thứ tự xong trước. Duyệt theo thứ tự rủi ro tăng dần hoặc theo thứ tự phụ thuộc: việc nào nền tảng hơn, chạm vào nhiều thứ hơn, gộp trước. Sau mỗi lần gộp vào nhánh chính, các nhánh còn lại cần được cập nhật theo nhánh chính mới, bằng cách gộp nhánh chính vào hoặc đặt lại gốc nhánh, tuỳ quy ước nhóm, rồi chạy lại kiểm thử ở worktree đó.
Bước cập nhật này hay bị bỏ vì các nhánh trông độc lập. Nhưng hai thay đổi độc lập về tệp vẫn có thể xung đột về hành vi: tác tử A đổi định dạng trả về của một hàm, tác tử B viết kiểm thử dựa trên định dạng cũ. Không có xung đột tệp nào, nhưng sau khi gộp cả hai, kiểm thử đỏ. Chạy lại kiểm thử sau mỗi lần cập nhật nhánh là cách duy nhất bắt được loại lỗi này.
Nếu có xung đột tệp thật, bạn có thể giao chính tác tử của nhánh đó giải quyết, vì nó còn bối cảnh việc vừa làm. Sau khi giải, đọc lại riêng các khối từng xung đột: đó là nơi tác tử dễ chọn bỏ thay đổi của phía kia nhất.
Dọn worktree sau khi xong
Worktree để lại sẽ chiếm chỗ đĩa, nhất là khi mỗi thư mục có bộ phụ thuộc riêng. Dọn ngay khi nhánh đã gộp hoặc bỏ:
- Xoá thư mục làm việc qua git: git worktree remove ../cuahang-kiemthu. Git từ chối nếu thư mục còn thay đổi chưa ghi nhận, nhắc bạn kiểm trước.
- Nếu lỡ xoá thư mục bằng trình quản lý tệp, chạy git worktree prune để git quên đi các thư mục không còn tồn tại.
- Xoá nhánh đã gộp bằng git branch -d kèm tên nhánh.
- Kiểm danh sách bằng git worktree list; chỉ nên còn thư mục kho chính và các phiên đang chạy.
Một quy ước nhỏ giúp nhiều: mọi worktree của tác tử đặt trong cùng một thư mục cha riêng, cạnh kho chính. Nhìn thư mục đó là biết đang có bao nhiêu phiên dở dang, và xoá hàng loạt khi cần cũng dễ. Khi chạy song song lâu dài, ghi lại trong ghi chú cá nhân phiên nào đang làm gì, vì sau một ngày nghỉ rất dễ quên.
Câu hỏi thường gặp
Có cách nào chạy song song mà không cần worktree?
Có thể sao chép kho thành nhiều bản riêng, mỗi bản một nhánh. Cách này tốn chỗ hơn và các bản không chia sẻ lịch sử cục bộ, phải đẩy lên kho từ xa mới thấy nhau. Một số công cụ tác tử tự tạo môi trường tách riêng cho mỗi phiên; khi đó bạn không cần tự dựng.
Worktree có làm hỏng kho chính không?
Không, nếu dùng qua lệnh git. Các worktree dùng chung kho đối tượng, nhưng mỗi thư mục có trạng thái làm việc riêng. Rủi ro chính là xoá thư mục bằng tay khi còn thay đổi chưa ghi nhận, nên dùng lệnh xoá của git.
Chạy song song có giúp việc lớn xong nhanh hơn?
Thường không, nếu việc lớn chạm nhiều chỗ liên quan nhau. Chia việc lớn thành các phần độc lập là việc khó, và nếu chia sai, thời gian giải xung đột và sửa lỗi hành vi sẽ ăn hết thời gian tiết kiệm. Song song hợp nhất với nhiều việc nhỏ, độc lập.
Mỗi worktree có cần cài lại toàn bộ phụ thuộc không?
Thường có, vì thư mục phụ thuộc không được git theo dõi. Với dự án lớn, việc này tốn thời gian và đĩa. Một số trình quản lý gói có bộ nhớ đệm dùng chung giúp cài lại nhanh; kiểm tài liệu của trình quản lý gói bạn dùng.
Hai tác tử có thể dùng chung một nhánh không?
Git không cho mở cùng một nhánh ở hai worktree, và cũng không nên tìm cách lách. Hai tác tử ghi nhận chồng lên một nhánh sẽ ghi đè việc của nhau. Nếu hai việc cần chung kết quả, làm tuần tự.
Có nên cho tác tử tự tạo worktree?
Được nếu công cụ hỗ trợ và bạn cho phép lệnh đó, nhưng nên để tác tử báo tên thư mục và nhánh nó tạo. Tự tạo bằng tay thì bạn kiểm soát tên và vị trí tốt hơn, nhất là lúc mới bắt đầu.