Nguyen Le PhongNguyen Le Phong

Trunk-Based Development

Một bài nhập môn thực tế về trunk-based development: merge nhỏ và thường xuyên, feature flag, test nhanh, code review discipline và thói quen team cần có để giữ main branch khỏe.

Merge conflict bắt đầu từ một file nhìn rất vô hại. Hai branch chạm vào cùng một function vì hai lý do khác nhau. Một branch thêm validation rule mới. Branch kia đổi shape của response. Cả hai thay đổi đều hợp lý. Nhưng sau vài ngày đi riêng, chúng tạo thành một câu đố nhỏ không ai muốn giải gần cuối sprint.

Trunk-based development một phần là câu trả lời cho nỗi đau đó. Ý tưởng rất đơn giản: developer integrate thay đổi nhỏ vào main branch thường xuyên, thay vì làm việc quá lâu trên branch tách riêng. Trunk, thường là main hoặc master, là shared line of development. Work vẫn có thể diễn ra trên short-lived branch, nhưng branch đó được đo bằng giờ hoặc một vài ngày, không phải nhiều tuần.

Lời hứa là feedback nhanh hơn. Khi change land thường xuyên, conflict nhỏ hơn, integration problem xuất hiện sớm hơn, và team nhìn thấy trạng thái thật của hệ thống sớm hơn. Continuous integration trở nên có ý nghĩa vì có một branch đại diện cho current truth. Main branch không phải ceremony. Nó là nơi team tiếp tục học cùng nhau.

Điều này không có nghĩa mọi người push behavior chưa xong trực tiếp tới user. Đây là hiểu nhầm phổ biến. Trunk-based development phụ thuộc vào các kỹ thuật tách code integration khỏi feature release. Feature flag, branch by abstraction, dark launch, configuration switch và backward-compatible change cho phép code merge trước khi behavior đầy đủ được bật cho product. Code có thể đã ở đó trong khi feature vẫn được kiểm soát.

Thay đổi nhỏ là nền tảng. Một pull request chỉ đổi một boundary, một behavior có thể test, hoặc một refactor chuẩn bị sẽ dễ review và an toàn hơn để merge. Branch lớn tạo rủi ro trễ. Chúng có thể cho cảm giác an toàn vì giữ work chưa xong ngoài trunk, nhưng thường cất chi phí integration như một khoản nợ sẽ đến hạn sau.

Test nhanh là điều không thể thiếu. Nếu main branch là shared truth, team cần confidence nhanh rằng nó vẫn chạy. Unit test, focused integration test, linting, type check và một nhóm critical end-to-end test nhỏ tạo thành safety net tối thiểu. Pipeline chậm hoặc flaky làm mọi người né merge, và cả practice bắt đầu mục rữa.

Code review cũng thay đổi. Reviewer cần phản hồi nhanh vì thời gian chờ dài biến short-lived branch thành long-lived branch. Standard review vẫn phải cao, nhưng đơn vị review nhỏ hơn. Thay vì bắt một pull request giải thích cả feature, mỗi pull request giải thích một bước an toàn. Design có thể nằm trong note riêng, còn code land theo từng slice.

Feature flag cần được tôn trọng. Chúng không chỉ là vài câu if. Team cần naming convention, owner, thói quen cleanup, observability và plan rõ để gỡ flag cũ. Nếu không, trunk-based development có thể đổi branch mess thành flag mess. Discipline không chỉ là merge nhanh. Nó là giữ production codebase vẫn dễ hiểu trong khi work chưa xong đi xuyên qua nó.

Trunk-based development cũng đòi hỏi trust. Developer cần tin rằng team sẽ giữ trunk khỏe, sửa broken build nhanh, không giấu risky work, và communicate khi change ảnh hưởng người khác. Main branch hỏng không phải sự xấu hổ của một cá nhân. Nó là interruption của team. Phản ứng trưởng thành là sửa signal, học vì sao nó xảy ra, và làm guardrail mạnh hơn.

Một số team chưa sẵn sàng nhảy một lần. Điều đó ổn. Một đường đi bình tĩnh hơn là rút ngắn branch lifetime trước, rồi cải thiện test, rồi dùng feature flag cho một loại change, rồi đo work integrate thường xuyên đến đâu. Mục tiêu không phải thắng tranh luận process. Mục tiêu là giảm bất ngờ integration ở cuối.

Câu hỏi phía sau trunk-based development là: chúng ta có thể rời xa sự thật trong bao lâu? Branch càng sống lâu, nó càng trở thành một phiên bản reality riêng. Integration thường xuyên đưa team quay lại shared reality sớm hơn, khi công việc vẫn còn nhỏ đủ để điều chỉnh.

Nếu team bạn từng chuyển từ long-lived branch sang trunk-based development, tôi muốn nghe điều gì thay đổi đầu tiên: merge conflict, nhịp review, test discipline, hay cách mọi người nói về work chưa hoàn thành.

Bạn thấy bài viết thế nào?