Chiến lược phân nhánh mã nguồn: Con đường dẫn đến sự vĩ đại

Tháng Chín 3, 2022
Nga Pham

Hầu hết các hệ thống kiểm soát phiên bản (Version Control System – VCS) ngày nay đều hỗ trợ các nhánh – các dòng công việc độc lập xuất phát từ một cơ sở mã nguồn trung tâm. Tuỳ thuộc vào hệ thống kiểm soát phiên bản, nhánh chính có thể được gọi là mainline, default hoặc trunk. Từ nhánh chính, các nhà phát triển có thể tạo nhánh của riêng họ và làm việc độc lập trên đó.

Tại sao phải chú ý đến việc phân nhánh?

Việc phân nhánh hỗ trợ các nhóm nhà phát triển cộng tác một cách dễ dàng trên một cơ sở mã trung tâm. Khi một nhà phát triển tạo một nhánh, hệ thống kiểm soát phiên bản sẽ tạo một bản sao của cơ sở mã tại thời điểm đó, các thay đổi sau này trên nhánh chính sẽ không ảnh hưởng đến nhánh riêng của các nhà phát triển. Rõ ràng đây là một điểm thuận lợi, vì các tính năng đang được phát triển không có tính ổn định và có thể gây gián đoạn nghiêm trọng nếu tất cả đều được phát triển trên nhánh chính. Tuy nhiên, các nhánh không nhất thiết phải tách biệt với nhau. Các nhà phát triển có thể dễ dàng pull các thay đổi của các nhà phát triển khác để cộng tác trên các tính năng và đảm bảo các nhánh riêng của họ không tách biệt quá xa so với nhánh chính.

Các nhánh không chỉ tốt cho việc phát triển tính năng, mà còn cách ly nhóm khỏi những thay đổi quan trọng về kiến trúc như cập nhật framework hay thư viện chung.

Ba chiến lược phân nhánh cho nhóm Agile

Các mô hình phân nhánh thường khác nhau giữa các nhóm và trở thành chủ đề của nhiều cuộc tranh luận trong cộng đồng phần mềm. Một chủ đề lớn là nên giữ bao nhiêu công việc trong một nhánh trước khi hợp nhất trở lại vào nhánh chính.

Release branching – Phân nhánh phát hành

Phân nhánh phát hành là ý tưởng chứa một bản phát hành hoàn toàn trong một nhánh. Có nghĩa là, vào cuối chu kỳ phát triển, người quản lý phát hành sẽ tạo ra một nhánh mới từ nhánh chính (ví dụ: 1.1 development branch). Tất cả các thay đổi cho bản phát hành 1.1 cần được áp dụng hai lần: một lần cho nhánh 1.1 và một lần cho mã nguồn chính. Làm việc với hai nhánh là công việc bổ sung cho nhóm và việc hợp nhất hai nhánh sẽ dễ bị bỏ sót. Việc sử dụng và quản lý các nhánh phát hành có thể trở nên khó khăn vì có nhiều người cùng làm việc trên một nhánh. Chắc hẳn tất cả mọi người đều cảm thấy bất tiện và không dễ dàng khi phải hợp nhất nhiều thay đổi khác nhau trên một nhánh duy nhất. Nếu bạn phải tạo một nhánh phát hành, hãy tạo nhánh gần với bản phát hành thực tế nhất có thể.

Lưu ý

Chiến lược phân nhánh theo bản phát hành là một phần quan trọng trong việc hỗ trợ phiên bản phần mềm đã được đưa ra thị trường. Một sản phẩm có thể có nhiều nhánh phát hành (ví dụ: 1.1, 1.2, 2.0) để hỗ trợ quy trình phát triển bền vững. Hãy nhớ rằng các thay đổi trong các phiên bản trước đó (ví dụ 1.1) có thể cần được hợp nhất trong các nhánh phát hành sau (1.2 hoặc 2.0).

Feature branching – Phân nhánh tính năng

Các nhánh tính năng thường được gắn cờ tính năng – là các toggle để kích hoạt hoặc vô hiệu hoá một tính năng trong sản phẩm. Cách tiếp cận này giúp quá trình triển khai mã vào nhánh chính và kiểm soát trạng thái kích hoạt tính năng trở nên dễ dàng và hiệu quả hơn trước khi tính năng đến với người dùng cuối.

Một lợi ích khác của cờ tính năng là mã có thể vẫn còn trong bản dựng nhưng không hoạt động khi đang được phát triển. Nếu có vấn đề xảy ra khi tính năng được kích hoạt, quản trị viên hệ thống có thể tắt kích hoạt tính năng và trở lại một trạng thái ổn định trước đó, thay vì phải triển khai một bản dựng mới.

Task branching – Phân nhánh tác vụ

Quy trình làm việc ở Atlassian là quy trình tập trung vào tác vụ: branch-per-task. Mọi tổ chức đều có một cách chia nhỏ công việc thành các task riêng lẻ trong một trình theo dõi issue, ví dụ như Jira Software. Các issue sau đó sẽ trở thành đầu mối liên hệ trung tâm về công việc tương ứng. Chiến lược Task branching (hay còn gọi là Issue branching) kết nối trực tiếp các issue với mã nguồn. Mỗi issue được thực hiện trên nhánh riêng với issue key bao gồm trong tên nhánh. Nhờ đó, thật dễ dàng để biết mã nguồn nào triển khai issue nào: chỉ cần tìm issue key trong tên nhánh. Với mức độ minh bạch cao như thế này, việc áp dụng các thay đổi cụ thể cho nhánh chính hoặc bất kỳ nhánh phát hành kế thừa có vòng đời lâu dài chắc chắn sẽ trở nên dễ dàng hơn. 

Vì sự linh hoạt xoay quanh các câu chuyện người dùng, các nhánh tác vụ kết hợp tốt với quy trình phát triển Agile. Mỗi câu chuyện người dùng (hoặc lỗi cần sửa) nằm trong nhánh riêng sẽ giúp bạn dễ dàng nắm bắt những vấn đề đang được xử lý và những vấn đề đã sẵn sàng để phát hành. 

Vấn đề không thể tránh khỏi khi phân nhánh: merge

Tất cả chúng ta đều đã trải qua cảm giác khó khăn khi cố gắng tích hợp nhiều nhánh vào một giải pháp hợp lý. Trước đây, các hệ thống kiểm soát phiên bản tập trung như Subversion đã khiến việc hợp nhất (merge) trở thành một công việc vô cùng khó khăn. Tuy nhiên, các hệ thống kiểm soát phiên bản mới hơn như Git và Mercurial đã mang đến một cách tiếp cận khác để theo dõi các phiên bản của các tập tin nằm trên các nhánh khác nhau.

Với Git, việc hợp nhất là không cần thiết – các nhà phát triển được giải phóng để khai thác toàn bộ sức mạnh của quy trình công việc phân nhánh.

Các nhánh có xu hướng tồn tại trong thời gian ngắn, điều này giúp chúng dễ dàng được hợp nhất và trở nên linh hoạt hơn trên toàn bộ cơ sở mã. Nhờ khả năng hợp nhất các nhánh thường xuyên và tự động – một phần của tích hợp liên tục (Continuous Intergration – CI) – và thực tế là các nhánh tồn tại trong thời gian ngắn chứa ít thay đổi hơn, “merge hell” đã trở thành dĩ vãng đối với các nhóm sử dụng Git và Mercurial.

Đó là lý do khiến chiến lược phân nhánh tác vụ trở nên tuyệt vời!

Xác thực, xác thực và xác thực

Một hệ thống kiểm soát phiên bản chỉ có thể tác động đến kết quả hợp nhất. Kiểm thử tự động và tích hợp liên tục cũng đóng vai trò cực kỳ quan trọng. Hầu hết các máy chủ CI có thể tự động đưa các nhánh mới vào thử nghiệm, giúp giảm đáng kể số lượng “bất ngờ” khi hợp nhất và góp phần duy trì tính ổn định cho mã nguồn chính.

Theo Atlassian