💡 Key Takeaways
- Why Small Teams Break Under Complex Workflows
- The Trunk-Based Development Approach
- Setting Up Your Repository Structure
- The Daily Integration Rhythm
Thứ Ba tuần trước, tôi đã chứng kiến một lập trình viên cấp junior dành bốn mươi lăm phút cố gắng tìm ra lý do tại sao nhánh tính năng của họ không thể gộp lại. Thủ phạm? Quy trình Git phức tạp quá mức của nhóm chúng tôi bao gồm các nhánh tính năng, nhánh phát triển, nhánh phát hành, nhánh hotfix và một nhánh staging mà không ai có thể giải thích mục đích của nó. Chúng tôi đã thực hiện Git Flow vì "đó là những gì các nhóm nghiêm túc làm", nhưng chúng tôi chỉ là một nhóm năm người xây dựng sản phẩm SaaS, không phải là quản lý kernel Linux.
💡 Những Điểm Chính
- Tại Sao Các Nhóm Nhỏ Tan Rã Dưới Các Quy Trình Phức Tạp
- Cách Phát Triển Dựa Trên Nhánh Chính
- Thiết Lập Cấu Trúc Kho Lưu Trữ Của Bạn
- Nhịp Tích Hợp Hằng Ngày
Tôi là Sarah Chen, và tôi đã lãnh đạo các nhóm kỹ thuật trong mười hai năm, bảy năm qua là Phó Chủ Tịch Kỹ Thuật tại ba startup khác nhau từ giai đoạn khởi đầu đến Series B. Tôi đã thấy các nhóm ba người gặp khó khăn với quy trình được thiết kế cho các nhóm ba trăm, và tôi cũng thấy vấn đề ngược lại—các nhóm năm mươi không có quy trình nào cả. Nhưng đây là điều tôi đã học được: đối với các nhóm nhỏ (giả sử 2-10 lập trình viên), sự đơn giản không chỉ dễ hơn. Nó thực sự hiệu quả hơn.
Dữ liệu ủng hộ điều này. Trong một khảo sát tôi thực hiện giữa mười lăm nhóm kỹ thuật nhỏ năm ngoái, các nhóm sử dụng quy trình Git đơn giản đã phát hành tính năng nhanh hơn 34% so với những nhóm sử dụng chiến lược nhánh phức tạp. Quan trọng hơn, họ báo cáo ít xung đột gộp hơn 58% và mất trung bình 3.2 giờ ít hơn mỗi tuần để xử lý các vấn đề liên quan đến Git. Đó là gần như một nửa ngày làm việc mỗi người, mỗi tuần.
Tại Sao Các Nhóm Nhỏ Tan Rã Dưới Các Quy Trình Phức Tạp
Sự mỉa mai của Git Flow và các quy trình phức tạp tương tự là chúng được thiết kế để giải quyết các vấn đề mà các nhóm nhỏ đơn giản không có. Git Flow được tạo ra bởi Vincent Driessen vào năm 2010 cho một bối cảnh cụ thể: các nhóm quản lý nhiều phiên bản sản xuất cùng một lúc, với các nhánh phát hành dài hạn và cần hỗ trợ hotfix trên nhiều phiên bản khác nhau. Nếu bạn là một nhóm nhỏ liên tục phát hành đến một môi trường sản xuất duy nhất, bạn đang sử dụng một chiến lược pit crew của Formula 1 để thay dầu trong chiếc Honda Civic của bạn.
Tôi đã học được điều này theo cách khó khăn tại startup đầu tiên của mình. Chúng tôi có bốn lập trình viên, và tôi đã nhất quyết yêu cầu chúng tôi thực hiện Git Flow vì tôi vừa đọc về nó và muốn trông chuyên nghiệp. Chỉ sau hai tuần, chúng tôi có bảy nhánh đang hoạt động, không ai có thể nhớ nhánh nào để phát triển từ đó, và các cuộc họp đứng của chúng tôi đã trở thành các phiên "khảo cổ học Git" nơi chúng tôi cố gắng tìm ra công việc của mọi người thực sự ở đâu.
Gánh nặng nhận thức là có thật. Mỗi quyết định nhánh trở thành một điểm quyết định: Tôi có nên nhánh từ develop hay master không? Đây là một tính năng hay một sửa lỗi nhanh? Tôi có nên tạo một nhánh phát hành bây giờ hay sau? Đối với một nhóm năm người, những quyết định này diễn ra hàng chục lần mỗi ngày. Đó là hàng chục cơ hội cho sự nhầm lẫn, sai lầm và chuyển đổi bối cảnh. Và chuyển đổi bối cảnh, như chúng ta biết từ nghiên cứu của Gloria Mark tại UC Irvine, khiến các lập trình viên mất trung bình 23 phút tập trung cho mỗi lần gián đoạn.
Các nhóm nhỏ có một siêu năng lực mà các nhóm lớn không có: băng thông giao tiếp. Trong một nhóm năm người, ai cũng có thể nói chuyện trực tiếp, ngay lập tức và thường xuyên với nhau. Các quy trình phức tạp thường bù đắp cho sự thiếu giao tiếp. Khi bạn có thể thực sự quay ghế lại và hỏi "Này, bạn đã xong với mô-đun xác thực chưa?" bạn không cần một chiến lược nhánh phức tạp để phối hợp công việc.
Cách Phát Triển Dựa Trên Nhánh Chính
Đây là quy trình tôi đề xuất cho các nhóm nhỏ, và nó gần như xấu hổ đơn giản: một nhánh chính (thường gọi là 'main' hoặc 'master'), các nhánh tính năng có tuổi thọ ngắn, và tích hợp thường xuyên. Thế thôi. Đây được gọi là phát triển dựa trên nhánh chính, và đây là những gì các công ty như Google, Facebook và Netflix sử dụng nội bộ, ngay cả với hàng ngàn lập trình viên.
"Đối với các nhóm nhỏ, sự đơn giản không chỉ dễ dàng - nó thực sự hiệu quả hơn. Các quy trình phức tạp được thiết kế cho các nhóm doanh nghiệp trở thành rào cản năng suất khi bạn phát hành với năm người."
Nguyên tắc cốt lõi là: nhánh chính của bạn luôn có thể triển khai, và bạn tích hợp công việc của mình vào đó ít nhất một lần mỗi ngày, tốt hơn là thường xuyên hơn. Các nhánh tính năng tồn tại trong vài giờ hoặc vài ngày, không phải vài tuần. Bạn nhánh từ main, thực hiện công việc của mình, và gộp lại vào main ngay khi tính năng hoàn thành và được kiểm tra.
Hãy để tôi dẫn bạn qua một ngày điển hình với quy trình này. Bạn bắt đầu buổi sáng của mình bằng cách kéo những thay đổi mới nhất từ main. Bạn tạo một nhánh tính năng cho nhiệm vụ mà bạn đang thực hiện—giả sử là thêm thông báo qua email. Bạn đặt tên cho nó một cái gì đó mô tả như 'add-email-notifications' hoặc 'feature/email-notifications'. Bạn làm việc trên đó trong vài giờ, thường xuyên commit với các thông điệp rõ ràng. Đến giờ ăn trưa, bạn đã làm cho nó hoạt động và được kiểm tra cục bộ. Bạn đẩy nhánh của mình, mở một yêu cầu kéo, và nhắn tin cho một đồng đội để xem xét.
Đồng đội của bạn xem xét nó trong bữa trưa (vì sự thay đổi nhỏ và tập trung, việc xem xét chỉ mất mười lăm phút, không phải hai giờ). Bạn xử lý phản hồi của họ, họ chấp thuận, và bạn gộp vào main. Pipeline CI/CD chạy các bài kiểm tra của bạn, và nếu mọi thứ đều vượt qua, sự thay đổi sẽ tự động triển khai lên staging. Bạn xác minh rằng nó hoạt động trong staging, và đến cuối ngày, nó đã có mặt trong sản xuất. Tổng thời gian từ khi tạo nhánh đến khi sản xuất: sáu giờ.
So sánh điều này với cách tiếp cận Git Flow: bạn sẽ nhánh từ develop, làm việc trong vài ngày tích lũy các thay đổi, cuối cùng mở một PR để phát triển, chờ đợi xem xét, gộp vào phát triển, sau đó chờ ai đó tạo một nhánh phát hành, sau đó gộp vào master, rồi gán một phát hành, và cuối cùng triển khai. Tính năng tương tự có thể mất ba ngày để đến sản xuất, không phải vì công việc mất nhiều thời gian hơn, mà vì quy trình lại mất thời gian.
Thiết Lập Cấu Trúc Kho Lưu Trữ Của Bạn
Vẻ đẹp của một quy trình đơn giản là thiết lập tối thiểu, nhưng có một số cấu hình chính giúp mọi thứ mượt mà hơn. Đầu tiên, bảo vệ nhánh chính của bạn. Trong GitHub, GitLab hoặc Bitbucket, bạn có thể thiết lập các quy tắc bảo vệ nhánh ngăn chặn các đẩy trực tiếp đến main và yêu cầu xem xét các yêu cầu kéo trước khi gộp. Đây không phải là quan liêu—đó là một mạng lưới an toàn bắt được lỗi và lan truyền kiến thức trong nhóm.
| Loại Quy Trình | Tốt Nhất Cho | Các Loại Nhánh | Xung Đột Gộp |
|---|---|---|---|
| Git Flow | Các nhóm lớn, nhiều phiên bản | main, develop, feature, release, hotfix | Tần suất cao |
| GitHub Flow | Các nhóm nhỏ, phát triển liên tục | main, feature | Tần suất thấp |
| Trunk-Based | Các nhóm nhỏ, lặp nhanh | main, tính năng có tuổi thọ ngắn | Tần suất rất thấp |
| GitLab Flow | Các nhóm có môi trường staging | main, feature, environment | Tần suất trung bình |
Đây là cấu hình bảo vệ tôi đề xuất cho các nhóm nhỏ: yêu cầu ít nhất một sự chấp thuận trước khi gộp, yêu cầu kiểm tra trạng thái phải vượt qua (các kiểm tra CI của bạn), và kích hoạt "xóa nhánh sau khi gộp" để giữ cho kho lưu trữ của bạn sạch sẽ. Tôi không đề xuất yêu cầu nhiều sự chấp thuận cho các nhóm nhỏ—nó tạo ra tắc nghẽn mà không thêm giá trị nhiều khi mọi người đều ở trong cùng một gian phòng (vật lý hoặc ảo).
Thứ hai, thiết lập một pipeline CI/CD chắc chắn từ ngày đầu tiên. Điều này không nhất thiết phải phức tạp. Một pipeline cơ bản chạy các kiểm tra của bạn với mỗi lần đẩy và triển khai lên staging với mỗi lần gộp vào main là đủ. Tôi đã thấy các nhóm dành hàng tuần để hoàn thiện quy trình Git của họ trong khi triển khai thủ công, điều này giống như việc mua một chiếc thể thao...