Chắc hẳn phần lớn chúng ta ở đây (suy đoán của mình) chưa từng tham gia đóng góp (contribute) vào một opensource nào đó ở trên Github, kể cả bản thân mình cho đến gần đây. Contribute mình muốn nói đến ở đây không phải về việc chúng ta tự publish các opensource library lên chính repository của chúng ta trên Github, cũng không phải việc trả lời các issues trên các Github repository, và cũng không phải thực hiện review các PR (Pull Request) trên các Github repository. Cái mà mình muốn nói ở đây là công việc chúng ta tạo ra các dòng code cho các feature mới, để fixbug, để refactor,… và rồi đưa những dòng code đó vào trong các opensource trên Github.
Phần lớn chúng ta đang sử dụng trực tiếp các opensource từ các repository center, hoặc khi gặp bug chúng ta clone về và tự fix bug trong đó, và dùng nó như là một submodule ở trong project (Việc này cần chú ý đến License của opensource, và mục đích project của chúng ta đang làm). Có khá nhiều nhược điểm khi làm bằng cách vừa rồi, nhưng để đảm bảo đúng mục đích của bài này mình xin phép chưa nói đến ở đây, chúng ta có thể thảo luận ở phần comment. Tuy việc contribute cho opensource không phải là mục đích chính của mình trong bài viết này, nhưng hi vọng qua đây bạn sẽ nắm được các bước cơ bản để contribute cho một opensource nào đó trên Github.
Mục đích chính của mình trong bài này là việc chúng ta cùng cân nhắc sử dụng cách tiếp cận contribute để áp dụng cho các dự án trong của công ty, cùng nhìn các khía cạnh, ưu nhược điểm giữa 2 cách tiếp cận đó là truyền thống, và contribute.
Cách tiếp cận truyền thống và vấn đề gặp phải
Đầu tiên mình sẽ summarize về cách tiếp cận truyền thống mà chúng ta đang làm trong một project.
Chúng ta có một repository trên Gitlab, thêm các thành viên của dự án vào trong dự án theo từng rule, setup một số rule cơ bản về merge/rebase, branches, template,… Sau đó trong giai đoạn phát triển, mỗi thành viên sẽ tạo branch (theo format của team) để thực hiện code trên đó, code, commit, code, commit,… tạo MR/PR.
Vấn đề gặp phải
Những step trên đâu đấy là các step cơ bản để đưa các dự án về đích, còn về đích theo kiểu tan tác, hay hùng tráng thì đấy là một câu chuyện khác mà có thể mình sẽ chia sẻ ở một bài viết khác.
Tất nhiên nếu mọi chuyện đều đẹp đẽ thì chúng ta đã không có bài này để thảo luận. Dưới đây là một số những điều mình nhận thấy sau nhiều tháng, năm nhìn lại project:
- Git Tree là một cái gì đấy cực kì kinh khủng và không muốn nhìn vào nó.
- Có hàng chục, hàng trăm branches, già có, trẻ có với muôn hình muôn vẻ.
Với Git Tree thì đó là một câu chuyện rất hay, nhưng xin phép để lại cho một bài khác đầy đủ hơn để giải quyết nó. Ở đây mình muốn nói đến về branches. Sự hỗn loạn, nhập nhằng của branches trong project là sự đóng góp, cống hiến của mỗi thành viên trong dự án. Ở đây mình bỏ qua các yếu tố như quên không xóa branch sau khi đã được merge vào branch chính, hay branch sai format, branch từa lưa tạo linh tinh xong không xóa, thì mỗi một thành viên trong dự án, vẫn có những branch cá nhân cần thiết như để thử nghiệm, một số branch đang trong quá trình phát triển, fix bug này kia. Với mỗi thành viên đã có số branch cá nhân như vậy, thì liệu một team nhiều người thì lượng branch tại một thời điểm sẽ như nào? Sẽ rất rất lớn phải không?
Cách tiếp cận mới – Contribute
Idea của cách tiếp cận này để giải quyết vấn đề về branches đó là:
Mỗi thành viên trong dự án sẽ không làm việc trực tiếp với repository chính của dự án nữa, mà sẽ làm việc với repository riêng của chính mình (mỗi thành viên), sau đó contribute vào repository chính của dự án.
Với cách tiếp cận này, tất cả những gì bạn làm, bạn nghịch, bạn vọc trên sourcecode nó thuộc về bạn, và chính bạn mà thôi, không ai biết hay nhìn tới cả (trừ khi người đó muốn). Có nghĩa là tất cả những thứ hổ lốn mà có thể bạn tạo ra sẽ không làm ảnh hưởng đến người khác. Cuối cùng là những cái gì là tinh hoa nhất của bạn, thì bạn contribute (tạo MR/PR) vào trong repository chính của dự án, đến lúc đó ai ai cũng trầm trồ ngưỡng mộ những gì bạn đã đóng góp.
Lý thuyết thì là vậy, tiếp theo đây, chúng ta sẽ phải thực hiện hóa nó. Các step làm sao để có thể thực hiện contribute được thì các bạn tham khảo và đọc tại đây.
Mô hình tổng quát có thể biểu diễn qua sơ đồ dưới đây (Mình assume các bạn đã hiểu hoặc đã đọc bài hướng dẫn contribute ở trên):
Như bạn thấy, tất cả những branches, những đoạn code thử nghiệm, những gì chưa hoàn hảo, bạn gói gọn nó trong repository của bạn mà không làm ảnh hưởng đến toàn bộ dự án. Và chúng ta cũng chỉ quan tâm tới workspace mà mình đang làm việc mà thôi, rất tập trung, và không bị làm phiền bởi người khác.
Một vài câu hỏi thường được hỏi khi sử dụng cách tiếp cận mới này
(Mình assume các bạn đã hiểu hoặc đã đọc bài hướng dẫn contribute ở trên)
1. Nếu source code nằm ở 2 repository khác biệt nhau như vậy, làm sao để source code ở fork repository của mình là mới nhất?
Trả lời: Ở máy tính của bạn đã được setup 2 remote URL, 1 là fork repository của bạn (origin), 2 là repository nguồn (upstream). Bạn có thể fetch source code ở upstream sau đó rebase sang source code local của bạn, sau đó push lên origin của bạn. Thật ra chúng ta sẽ thường quan tâm nhất trạng thái source code ở branch mà chúng ta đang dùng làm source base đó là branch develop
, hoặc master
.
2. Khi làm việc trong dự án, thỉnh thoảng vẫn cần base trên source code của đồng nghiệp để làm, vậy thì phải làm thế nào?
Trả lời: Tương tự với cách mà chúng ta setup git remote upstream, chúng ta hoàn toàn có thể setup git remote vào fork repository của đồng nghiệp bằng cách git remote add TEN_DONG_NGHIEP FORK_REPOSITOY_URL_DONG_NGHIEP
. Ví dụ như git remote add DoanNH3 https://github.com/ngohado/project-a
. Sau đó chúng ta hoàn toàn có thể base trên branch nào đó của đồng nghiệp để thực hiện tiếp.
Sau khi làm việc xong, chúng ta có thể remove remote của đồng nghiệp đi để tránh rối rắm workspace của chúng ta.
3. Nếu tôi là teamlead của dự án, tôi muốn xem công việc hiện tại của các thành viên xem tình hình code đến đâu rồi, code thế nào, chẳng lẽ tôi phải remote đến tất cả các repository của member à? Liệu có cách nào tốt hơn không?
Trả lời: Bản thân nếu bạn phải remote sang tất cả repository của member, cũng sẽ không khác gì, chứ không tồi tệ hơn cách cũ. Tuy nhiên nếu là mình, mình sẽ thực theo cách như sau:
- Member sẽ tạo MR/PR ngay khi bạn ấy push commit lần đầu tiên (mình prefer anh em member luôn luôn push ít nhất 1 lần / ngày làm việc, đó là trước khi rời office).
- Mình thích review theo từng commit chứ không phải tổng thể MR/PR (tất nhiên cái này cả team phải chung một mindset thì mới làm được), nên nếu commit nào đã hoàn thiện bạn ấy đẩy lên mình có thể review được ngay, còn những commit vẫn in-progress chưa sẵn sàng thì có thể thêm prefix vào commit message để báo với teamlead chưa review commit đó (Bước refine commit sau khi hoàn tất mình sẽ có một bài chia sẻ riêng).
Với cách trên thì mình có thể view được tình hình của team qua các MR/PR, qua các commit đã hoàn thiện, và các commit vẫn đang trong progress.
Kết luận
Bản thân mình chưa trải nghiệm cách tiếp cận này trên một project dài hơi, hay lớn. Mình tin là vẫn sẽ có những question cho cách tiếp cận này, nếu bạn có hãy raise lên ở dưới phần comment để chúng ta cùng nhau nghĩ cách giải quyết. Nếu sắp tới khi mình tham gia vào một dự án nào mới, mình nhất định sẽ đề xuất cách tiếp cận này để trải nghiệm, có đánh giá tốt hơn và rồi sẽ chia sẻ lại cho mọi người. Thật ra thì không hẳn là dự án mới mới có thể áp dụng được, ngay những dự án đang chạy hoàn toàn có thể chuyển sang cách này, nếu thấy hợp lý thì hãy thử đề xuất với teamlead, hay với team của chính các bạn nhé. Cảm ơn các bạn đã đọc đến đây, rất mong nhận được sử phản hồi từ các bạn.