Bản ghi video (Phần 2):
Chào mừng đến với Phần 2 của Chiến lược Phân nhánh. Tên tôi là Tomaz Borstnar. Trong Phần 1, chúng ta đã nói về các chiến lược phân nhánh và một số quy trình công việc có thể có, quy trình điển hình là quy trình làm việc tập trung nơi bạn làm mọi thứ trong một nhánh duy nhất và quy trình còn lại là quy trình làm việc theo nhánh tính năng. Và khi bạn cần thứ gì đó để sẵn sàng sản xuất, có thể mở rộng, khi bạn muốn có sự phản ứng nhanh chóng với một vấn đề cấp bách, bạn cần một thứ như GitFlow. Với GitFlow, bạn thường có ít nhất hai nhánh chính.
Đầu tiên là nhánh Master. Nhánh Master phải luôn ổn định. Bạn nên cẩn thận với những gì bạn đặt ở trong nhánh này. Bởi vì về mặt lý thuyết, trong bất kỳ thời điểm nào trong tương lai, bạn có thể được yêu cầu thực hiện một bản phát hành mới. Để công việc chính tiếp tục, bạn nên có một nhánh khác. Trong trường hợp này, nó được gọi là các nhánh development. Khi bạn cần làm việc trên các tính năng, bạn phải tạo các nhánh riêng biệt cho các tính năng đó. Và sau đó các tính năng đó được merge vào nhánh Master.
Khi ai đó cần làm việc trên nhánh Master, không ai có thể trực tiếp thực hiện commit trên đó. Nếu ai đó cần thay đổi, chỉnh sửa hay bổ sung code, cách tiếp cận tốt nhất sẽ là tạo một bản sao của code, làm việc trên đó, commit ở một chỗ khác. Sau khi nó được xem xét và phê duyệt, nó có thể chuyển đến nhánh Master.
Trong đa số trường hợp, nhánh Master phải được bảo vệ. Không phải developer nào cũng có quyền thực hiện commit ở đó. Chỉ project manager hoặc các senior developers mới được thực hiện những thay đổi trên đó.
Sau đó, bạn cũng thường muốn sử dụng một cái gì đó được gọi là thẻ (tag). Về cơ bản, một tag là một điểm đánh dấu của phiên bản phần mềm hiện tại, đối với mỗi phiên bản mà bạn phát hành, bạn phải tạo một tag. Tag có thể là 1.0, 1.12, v.v. Về cơ bản đây là những điểm đánh dấu thời gian để người dùng dễ dàng hơn trong việc xem trạng thái cụ thể của repository đối với từng phiên bản là gì, điều này rất quan trọng với các trường hợp chúng ta muốn thực hiện các bản vá sửa lỗi.
Nếu bạn là một developer làm việc với bug fix, điều quan trọng là phải lấy chính xác trạng thái của source code cho phiên bản đó. Và bạn chỉ thực hiện sửa những lỗi cần thiết, sau đó merge trở lại vào nhánh. Khi có một bản phát hành ứng dụng mới được chuẩn bị, thì về cơ bản, một tag mới sẽ được tạo.
Vì vậy, khi bạn sử dụng GitFlow với nhánh phát hành, bạn bắt đầu chuẩn bị code cho bản phát hành thực tế, đây là nhánh có rất nhiều hạn chế. Bên trong nhánh đó, bạn không nên đặt bất kỳ tính năng nào. Bạn chỉ nên đặt các bản sửa lỗi và các commit liên quan đến bản phát hành.
Ý tưởng ở đây là nhánh này được kiểm tra rất thường xuyên, nên nó phải ở trạng thái tĩnh (static state) cho đến khi nó được tuyên bố là ổn định. Và tất cả những thay đổi được thực hiện ở đây, lý tưởng nhất là sau đó cũng nên được hợp nhất vào nhánh chính để bạn không bị thiếu bất kỳ đoạn code nào.
Những ý trên là cho các bản phát hành thông thường. Nhưng còn vấn đề về các hotfix? Hotfix về cơ bản là một lỗi cấp bách. Nó có thể là một lỗi bảo mật. Như tên gọi của nó, hotfix là một cái gì đó có mức độ ưu tiên cao. Ý tưởng là nó sẽ khắc phục các vấn đề quan trọng cần được khắc phục càng sớm càng tốt.
Vì vậy, những gì bạn thường làm, bạn phân nhiều nhánh từ master branch. Ở đó, bạn chỉ có những commit liên quan trực tiếp đến vấn đề quan trọng. Và bất cứ thứ gì được sửa ở đó sau đó cũng được merge vào nhánh master, cũng như là các nhánh development, để tất cả mọi người có thể xem qua đoạn code đó.
Bằng cách sử dụng phương pháp này, bạn có thể xoay xở rất nhanh. Vì vậy, các nhà phát triển có thể làm việc trên các tính năng mới mà không bị chậm lại, không có bất kỳ giới hạn nào, đồng thời, bạn vẫn có thể có một môi trường ổn định, nhất quán. Khi cần, bạn có thể phát hành một phiên bản phần mềm mới, ổn định. Và bạn cũng có thể nhanh chóng khắc phục các sự cố cấp bách ngay lập tức.
Đây thực sự là phương pháp tốt nhất được khuyến nghị giúp bạn nhanh chóng phản hồi mọi thứ, giúp bạn có một phiên bản đã được thử nghiệm tốt. Và quan trọng là các nhà phát triển không bị chậm lại khi chờ đợi lẫn nhau.
Cảm ơn bạn đã xem Chiến lược phân nhánh.
Phát triển phần mềm là một quá trình liên tục bao gồm nhiều thứ hơn là chỉ hiểu ngôn ngữ lập trình và các công cụ. Hầu hết các dự án bây giờ phức tạp đến mức chúng không thể được thực hiện riêng lẻ nữa. Thay vào đó, cả một nhóm phải được tập hợp và quản lý để làm việc nhất quán và hiệu quả.
Các dự án hiếm khi được xác định cụ thể ngay từ đầu và thực tế chúng ta thường không có thời gian hoặc lý do để xác định mọi thứ chi tiết trước khi triển khai thực tế. Việc phát triển phần mềm cần xem xét thực tế là các yêu cầu của dự án có thể sẽ thay đổi thường xuyên và sẽ tập trung vào những gì khách hàng thực sự cần. Phần mềm dự kiến sẽ được kiểm tra kỹ lưỡng trước khi đưa vào sản xuất, nó phải được nâng cấp và cải tiến liên tục, và nếu nhận thấy bất kỳ lỗi nào, bản phát hành mới cần được sẵn sàng và triển khai càng sớm càng tốt.
Git, với tư cách là một VCS phân tán, là công cụ cộng tác quan trọng nhất của đội ngũ phát triển phần mềm. Cùng với hệ thống theo dõi (tracking system), nó xác định môi trường làm việc, nơi có thể đáp ứng tất cả những yêu cầu của bạn. Bên cạnh những công cụ như Git, nhóm cần tự tổ chức để tuân theo các quy tắc xác định của quy trình làm việc.
Git cung cấp cho bạn sự hỗ trợ phân nhánh hiệu quả giúp việc tạo các nhánh và chuyển đổi giữa chúng dễ dàng và nhanh chóng. Điều đó thúc đẩy việc sử dụng Git trên nhiều góc nhìn. Các chiến lược khác nhau đã được phát triển, dựa trên sự đơn giản của phân nhánh, mà bạn có thể sử dụng để phát triển các ứng dụng một cách nhất quán và hiệu quả nhất.
Chung cho tất cả các chiến lược là tất cả mọi người trong đội ngũ phát triển phải đồng ý về cách các đóng góp sẽ được áp dụng cho dự án hay nói cách khác, quy trình làm việc Git phải được tuân thủ nghiêm ngặt. Chiến lược phân nhánh (hay có thể hiểu là việc chia dự án lớn thành những nhánh công việc nhỏ trong từng branch cụ thể) phải được truyền đạt đến từng thành viên bằng cách sử dụng một tài liệu tham khảo như mô tả trên trang wiki, email, hoặc ít nhất là nó phải được trao đổi thông qua một cuộc họp. Một chiến lược phân nhánh được xác định rõ ràng sẽ cải thiện đáng kể cả chất lượng công việc và giao tiếp của nhóm. Mọi người đều hiểu rõ về cách tổ chức phát triển và các developers có thể hành động hướng tới mục tiêu chung.
Quy trình làm việc đã chọn có thể thay đổi trong quá trình phát triển. Những tình cảnh mới có thể phát sinh làm thay đổi động lực làm việc, nhưng điều đó có thể là lí giải đơn giản rằng nhóm đang hoạt động không tối ưu. Trong trường hợp đó, không phải là một ý tưởng tồi nếu ta tập hợp nhóm phát triển lại và đánh giá xem có nên đơn giản hóa hay mở rộng mức độ phức tạp của quy trình làm việc Git hay không. Khi làm điều đó, bạn nên xem xét văn hóa của nhóm, các yêu cầu của dự án và lưu ý rằng quy trình làm việc nên có các điều sau:
• Đối phó tốt với quy mô của nhóm (hiện tại và tương lai)
• Không nên tạo ra quá nhiều chi phí không cần thiết làm hạn chế năng suất
• Cần có cơ chế thích hợp để dễ dàng sửa đổi những sai lầm và cho phép phản ứng nhanh chóng với những thay đổi tiềm ẩn trong các yêu cầu của dự án
Về mặt kỹ thuật, Git không phân biệt giữa các nhánh chính và bất kỳ nhánh nào khác. Cách bạn làm việc với chúng có thể được xác định bằng một trong hai cách tiếp cận quy trình làm việc độc lập đã được nêu trên, quy trình làm việc theo mô hình tập trung và quy trình làm việc theo nhánh tính năng.
Centralized Workflow (Quy trình làm việc tập trung)
Nhóm của bạn chỉ có thể sử dụng Git làm điểm vào duy nhất cho tất cả các thay đổi đối với dự án. Quy trình làm việc tập trung, đúng như tên nó được gọi, chỉ sử dụng một nhánh Git cho tất cả các thay đổi. Với cách tiếp cận này, bạn có khả năng làm việc song song và hợp nhất tất cả công việc thành một nhánh duy nhất. Quy trình làm việc đơn giản như vậy có thể phù hợp cho một số dự án nhỏ hoặc dự án thiên về tài liệu. Ví dụ: nó phù hợp với một số dự án như các dự án code, trong đó các tệp định nghĩa có thể đọc được bằng máy sẽ được hiển thị bằng các tệp dưới source control.
Đối với các dự án lớn hơn thiên về ứng dụng, việc chỉ sử dụng một nhánh Git duy nhất sẽ hạn chế nghiêm trọng tính linh hoạt của bạn. Ví dụ, một tình huống tiến thoái lưỡng nan nảy sinh khi một phần mềm đã được phát hành. Nhóm phát triển của bạn sẽ làm gì sau đó? Làm việc trên bản phát hành theo lịch trình tiếp theo hay chờ để khắc phục các sự cố tiềm ẩn sau khi triển khai sản phẩm? Thực tế là mọi thay đổi về code đều tiềm ẩn một số tác dụng phụ. Với quy trình làm việc tập trung, các nhánh trở nên không ổn định vào thời điểm nhóm của bạn tiếp tục triển khai các tính năng mới và không sẵn sàng phát hành nữa.
Trong quy trình làm việc tập trung cơ bản, các nhà phát triển phải đợi nhau hoàn thành công việc của họ trước khi phần mềm có thể được phát hành. Hãy tưởng tượng rằng hai trong số thành viên của đội ngũ phát triển đang làm việc trên các tính năng mới khác nhau — một tính năng đơn giản và một tính năng phức tạp đòi hỏi nhiều thời gian phát triển. Trong môi trường CI / CD, việc đợi tất cả các nhà phát triển hoàn thành là không thể chấp nhận được.
Feature Branch Workflow (Quy trình làm việc theo nhánh tính năng)
Thay vì chỉ sử dụng nhánh chính, các nhà phát triển có thể tuân theo quy trình làm việc của nhánh Feature – nhánh tính năng và làm việc độc lập trong một nhánh dành riêng cho từng tính năng. Với cách tiếp cận đó, code trong nhánh chính có thể được giữ nguyên và ổn định cho đến khi tính năng mới kết thúc. Chỉ sau khi tính năng mới đó được hợp nhất trở lại nhánh chính. Không cần phải chờ đợi, vì mỗi nhánh được hợp nhất đại diện cho một tác phẩm đã hoàn thành khiến nhánh chính sẵn sàng cho các quy trình CI tiếp theo và có khả năng là một bản phát hành mới.
Bạn cũng có thể đẩy nhánh tính năng vào kho lưu trữ từ xa (repo). Việc cấp cho mọi người quyền truy cập vào nó cho phép bạn thực hiện những việc sau:
• Tạo một bản sao lưu phân tán
• Chia sẻ khối lượng công việc bằng cách cho phép người khác đóng góp
• Nhận phản hồi, như đánh giá code hoặc phê duyệt chung
• Đưa việc triển khai của bạn vào các quy trình thử nghiệm
Trong suốt thời gian tồn tại của dự án, bạn có thể mong đợi một số thay đổi ưu tiên. Có thể quyết định rằng tính năng bạn hiện đang triển khai không cần thiết nữa hoặc một số tính năng khác có mức độ ưu tiên cao hơn. Trong trường hợp đó, bạn không cần phải từ bỏ toàn bộ công việc của mình. Bạn có thể chỉ cần thực hiện công việc của mình, quay lại nhánh chính và tạo một nhánh tính năng mới.
Nhìn chung, bạn nên thỉnh thoảng thực hiện merge nhánh chính vào nhánh tính năng của mình. Bằng cách đó, bạn có thể xử lý xung đột dần dần khi chúng xảy ra và sẽ không bị quá tải xung đột khi bạn merge tất cả các công việc đã hoàn thành của mình trở lại nhánh chính. Bạn cũng có thể phát hiện các thay đổi tính năng khác do các thành viên trong đội ngũ phát triển của bạn giới thiệu, kết hợp với đóng góp của bạn, thậm chí có thể phá vỡ code. Điều đó hoàn toàn ổn nếu nhánh tính năng của bạn tạm thời bị hỏng. Tuy nhiên, nếu điều đó xảy ra trên nhánh chính, nó có thể dẫn đến vài giờ lãng phí để sửa và phản ứng tức giận từ mọi người.
GitFlow — Nhánh Master và Nhánh Development
Hầu hết công việc phát triển được thực hiện bằng cách triển khai các tính năng mới và hợp nhất chúng vào nhánh chính. Điều đó được xử lý độc đáo với quy trình làm việc nhánh tính năng. Tuy nhiên, nó vẫn chưa đủ để bao gồm tất cả các trường hợp mà bạn có thể gặp phải trong quá trình tích hợp và phát triển ứng dụng. Các dòng công việc Git khác sử dụng quy trình làm việc nhánh tính năng làm nền tảng và mở rộng nó với việc thêm các định nghĩa, phân loại thành nhiều loại nhánh khác và các quy tắc để sử dụng chúng.
GitFlow là một trong những chiến lược phân nhánh bao gồm tất cả các yêu cầu đối với hoạt động CI / CD. Nhìn chung, đó là một quy trình làm việc toàn diện với nhiều loại nhánh khác nhau và một bộ quy tắc về cách làm việc với chúng. Bạn có thể nghĩ rằng nó quá phức tạp đối với dự án nhỏ của bạn, nhưng điều quan trọng là bạn phải hiểu tại sao một số quy tắc được đưa ra và chúng đạt được những gì. Sau đó, bạn có thể quyết định sử dụng toàn bộ các quy tắc hay chỉ một tập hợp con của nó.
Cải tiến rõ ràng đầu tiên là, thay vì một nhánh chính duy nhất, quy trình làm việc này sử dụng hai nhánh chính để ghi lại lịch sử của dự án. Nhánh Master – (nhánh chính) được sử dụng để duy trì lịch sử phát hành, trong đó mỗi bản phát hành được gắn thẻ (tag) với số phiên bản được chỉ định. Nhánh thứ hai là nhánh Development – (nhánh phát triển), một nhánh tích hợp nơi mà tất cả các nhánh Features – (nhánh tính năng) được hợp nhất vào.
Có sự khác biệt đáng kể giữa hai nhánh này. Trong khi ở nhánh Development là một quy trình công việc không bao giờ kết thúc với rất nhiều merges và commits được thực hiện trực tiếp, thì nhánh Master chỉ có các merge commits với code ổn định, đã được kiểm duyệt và mỗi commit tương quan với một bản phát hành thực tế. Nhánh Master chỉ chứa code và các tệp tài nguyên khác cần thiết cho một bản phát hành và triển khai nó. Mặt khác, nhánh Development có thể bao gồm các công cụ và tài nguyên bổ sung chỉ dùng trong quá trình phát triển ứng dụng chứ không phải cho người dùng. Ví dụ: có thể có một số công cụ kiểm tra chỉ dành cho đội ngũ phát triển sử dụng mà không bao giờ được phát hành công khai, do đó được lọc ra khỏi nhánh Master.
GitFlow — Nhánh Release
Khi nhánh Development đã triển khai đủ các tính năng cần có ở bản phát hành theo lịch trình, nhóm của bạn phải làm việc để làm cho phiên bản đủ ổn định để phát hành. Thay vì dừng tất cả các phát triển mới, bạn nên phân sang một nhánh khác được gọi là nhánh Release – nhánh phát hành. Mục đích duy nhất của nhánh này là chuẩn bị code cho bản phát hành thực tế..
Ý tưởng cơ bản là nhánh phát triển vẫn có thể được phát triển thêm. Hầu hết nhóm của bạn không phải chậm lại và có thể tiếp tục với quy trình làm việc của nhánh tính năng trên nhánh phát triển bằng cách commit các tính năng dành cho bản phát hành tiếp theo.
Tuy nhiên, ở nhánh Release mới được tạo, mọi thứ đều chậm lại. Việc thực hiện các commit tính năng mới bị dừng lại và chỉ cho phép các bản sửa lỗi và các commit liên quan đến bản phát hành. Để tránh nhận được bất kỳ commit không ổn định nào trước khi phát hành, việc merge chỉ giới hạn ở một hướng, theo hướng quay ngược trở lại nhánh phát triển.
Một khi nhánh phát hành đủ ổn định, một "code freeze" được tuyên bố, hạn chế tất cả các commits tiếp theo mà không có sự chấp thuận cụ thể. Sau khi đánh giá chu đáo, ta mới đưa ra quyết định merge nhánh phát hành này vào nhánh chính. Cam kết hợp nhất được gắn thẻ tag với số phiên bản được chỉ định cho bản phát hành thực tế. Nếu cần, bạn nên hợp nhất nhánh phát hành với nhánh phát triển lần cuối.
GitFlow — Nhánh Hotfix
Đôi khi một lỗi nghiêm trọng phát sinh sau khi phát hành. Không quan trọng là báo cáo đến từ người dùng hay quá trình thử nghiệm của đội ngũ phát triển ứng dụng, thời gian xuất hiện lỗi là năm phút trước hay vài tháng sau khi phát hành. Trong bất kì trường hợp nào đi nữa, một phản ứng nhanh chóng với một bản phát hành hoàn toàn mới nên được thực hiện ngay.
Cách duy nhất để làm điều đó là nhanh chóng bắt đầu với một nhánh master ổn định khác và tách nhánh Hotfix – nhánh sửa lỗi cấp bách ra khỏi nó. Khi bản sửa lỗi được thực hiện và xác minh, nó nên được merge vào cả hai nhánh chính và nhánh phát triển. Số phiên bản phải được cập nhật tương ứng và được sử dụng làm thẻ phát hành trên nhánh chính.
GitFlow — Tổng quan
GitFlow duy trì hai nhánh chính vì một lý do rất chính đáng. Để trở thành một nhóm phát triển có khả năng phản hồi cao, bạn phải luôn có sẵn một nhánh đủ ổn định để phát hành các phiên bản của ứng dụng. Với nhánh chính, bạn có thể cải thiện nhanh chóng phiên bản hiện đang phát hành tại bất kỳ thời điểm nào. Với các nhánh hotfix, việc sửa chữa, kiểm tra và phân phối khẩn cấp, có thể rất hỗn loạn, vẫn được thực hiện một cách minh bạch. Phản hồi nhanh với các lỗi có thể được sắp xếp theo cách có kiểm soát, chỉ giới hạn các thay đổi đối với vấn đề liên quan, do đó thu hẹp phạm vi kiểm tra lại.
Mặt khác, ở nhánh phát triển là một quy trình công việc không bao giờ ngừng nghỉ để đội ngũ phát triển liên tục cải thiện phần mềm, ứng dụng. Ngược lại với nhánh master, nhánh development không cần phải luôn ổn định, bởi vì các nhánh release sẽ đảm nhiệm chuyện đó. Bằng cách đó, các thành viên trong nhóm có thể làm việc rất nhanh chóng mà không bị gián đoạn hoặc mất thời gian tập trung vào việc đánh bóng các chi tiết.
Các chi tiết sau đó được đánh bóng trong các nhánh release, nơi dễ dàng thực thi một số hạn chế cần thiết hơn, chẳng hạn như xác định những gì đã ổn định sẽ được đưa vào bản phát hành và những gì nên để lại cho phần tiếp theo để tiếp tục phát triển. Quá trình kiểm tra đột nhiên thu hẹp lại, có thể quản lý được và dần dần dừng lại khi nhánh được coi là ổn định. Các nhánh phát hành ổn định sau đó được hợp nhất trở lại nhánh phát triển, điều này giúp cải thiện đáng kể việc phát triển ứng dụng.
Tất cả các loại nhánh khác nhau này cung cấp sự tách biệt rõ ràng giữa các giai đoạn phát triển, sửa lỗi, phát hành giúp quản lý hiệu quả hơn quy trình làm việc của nhóm.
VNPRO