Android

Git, Bài 4: Các nhánh (branches)

git_logo

Sếp lớn đùng một cái giao cho nhóm của bạn phải thực hiện một ứng dụng hoàn toàn mới. Sau khi thảo luận vài ngày thì cuối cùng nhóm cũng thống nhất về thiết kế cũng như các công việc hậu cảnh về phía Service của ứng dụng cũng như phần server. Và vì thời gian gấp gáp, cũng như số lượng các thành viên trong nhóm không ít, nên việc các thành viên được phân công các phần việc mang tính chuyên môn là điều tất nhiên. Ai lo giao diện thì tập trung làm giao diện, kẻ làm background thì chỉ quan tâm tới background… Lí thuyết là vậy, nhưng trên thực tế thì cần phải thường xuyên tổng hợp các phần của project lại để kiểm tra, điều chỉnh sao cho cả dự án có hiệu quả tốt nhất. Và giai đoạn này, nếu không có Git branch thì mọi thứ sẽ vô cùng phức tạp và rối rắm, và tội nghiệp nhất là người đứng ra tổng hợp, thống nhất các files của project.

1. Ý tưởng chung về Git branch:

Bây giờ, bạn khoan nghĩ về lập trình, mà hãy đặt mình vào vai trò người nội trợ. Hôm nay, bạn là cùng với vài người nữa chuẩn bị một bàn ăn với nhiều món khác nhau. Và sau khi đã có các nguyên liệu, thì mỗi người đầu bếp sẽ lấy đúng các thứ mình cần để làm món ăn mà mình được giao. Nếu đem so sánh với hoạt động lập trình, thì mỗi người đầu bếp đang thực hiện một nhánh – branch – của Git. Cuối cùng, tất cả đầu bếp sẽ dọn thành quả của mình lên bàn, tổng hợp các món đã được yêu cầu, bạn sẽ có được một bàn ăn hoàn chỉnh – so lại với Git thì đây là công tác merge branches, tức tổng hợp/gộp các nhánh lại với nhau.

2. Cách hoạt động của branch:

Mặc định, khi khởi tạo Git trong project, nó sẽ cung cấp cho chúng ta một branch mặc định. Branch này thường có tên là master, mặc dù bạn có thể chỉ định dùng tên khác ngay từ đầu hoặc đổi sang bất cứ tên nào mà bạn thích, cũng “chơi trội” bằng cách tạo một branch có tên primary rồi sử dụng nhánh đó làm nhánh chính. Đường nào cũng tới La Mã, miễn hợp ý và bạn biết mình đang làm gì là được. Ở đây, tôi sử dụng nhánh master làm nhánh chính và các devs khác cũng ít ai lập dị mà chọn tên khác.

Như trong hình minh họa bên dưới, nhánh master là nhánh màu đỏ, sẽ là nhánh xuyên suốt của project. Tất cả các phiên bản stable/public release (hay ổn hơn là milestone) sẽ được built từ nhánh master này.

Git branches

Từ nhánh master, khi cần tạo nhánh thì bạn cho sinh ra thêm các nhánh khác, được biểu thị bằng màu xanh lá và xanh lam, và mỗi nhánh có các commits riêng của nó. Và như bạn thấy trong hình minh họa, chúng sẽ được nhập trở lại vào nhánh master. Thông thường, khi đã phân nhánh con, thì tạm thời các devs sẽ không commit vào master branch trừ khi điều đó là vô cùng cần thiết, rất khẩn cấp và cần được duy trì về sau, chẳng hạn các sửa lỗi có quy mô lớn, tính chất nguy hiểm, thì cần commit ngay vào nhánh master luôn, và phát hành ngay và luôn bản cập nhật vá lỗi, mà không chờ các nhánh con xong xuôi được.

Ví dụ thực tế, sau khi khởi tạo project xong, tích hợp Git vào xong, bao gồm việc master branch đã được tạo, thì các thành viên trong nhóm sẽ tiến hành tạo các branch khác nhau để thực hiện phần nhiệm vụ của mình, chẳng hạn branch về UI, branch về Services, branch về backend server, v.v… Và cuối cùng, khi “lắp ráp” lại, thì mọi dòng code sẽ được quy tựu lại vào master branch.

3. Tạo, chuyển và xóa branch:

Việc tạo branch mới đơn giản tới mức không ngờ! Và thực tế thì các câu lệnh của Git hoàn toàn không có gì phức tạp. Lần này, sau từ khóa “branch” sẽ là tên nhánh. Chẳng hạn, tôi muốn tạo một branch mới có tên là user-interface, thì tôi chỉ thực thi câu lệnh bên dưới, với yêu cầu là bạn đang trỏ vào thư mục project của bạn:

Tất nhiên, sau này bạn muốn tạo nhánh mới thì cứ chạy câu lệnh trên trên bất kì nhánh nào, không nhất thiết phải quay về master rồi mới tạo nhánh mới. Tuy nhiên, khoan thực hiện chỉnh sửa vội, vì hiện tại là bạn chưa “nhảy nhánh”, tức là còn đứng ở nhánh cũ, chưa “chuyền cành” sang nhánh mới. Để chuyển sang thao tác trên nhánh vừa tạo, hay sau này là nhánh nào khác, thì bạn sẽ phải check out tên nhánh đó. Nhưng trước hết, để xem tình trạng các nhánh thì bạn có thể thực thi câu này:

Thông tin về các branches sẽ được liệt kê. Sau khi nhận thấy đã xuất hiện branch mới, bạn có thể check out để chuyển sang nhánh mới đó. Trong trường hợp này là nhánh user-interface:

Nếu phần output của Command Prompt hay Terminal hay Power Shell báo “Switched to branch <branch-name>” là bạn đã chuyển nhánh thành công. Để chuyển lại nhánh master, bạn chỉ việc checkout nó mà thôi. Lưu ý là sau khi checkout lại master branch thì các files sẽ trở lại đúng trạng thái của nhánh master, vì vậy bạn đừng bất ngờ khi các tập tin bạn tạo cũng như thay đổi nội dung trong branch khác bỗng dưng trở lại trạng thái cũ để rồi “bỗng dưng muốn khóc” rồi nghĩ sai là mọi thay đổi của mình đã không cánh mà bay. Bạn phải nhớ là Git trực tiếp thay đổi các tập tin của bạn. Để đem mọi thứ lại như cũ, bạn chỉ việc checkout lại nhánh mà mình đang thao tác mà thôi.

Sau khi bạn đã thao tác với nhánh của mình xong, đã merge branch xong (xem phần bên dưới) và bạn cảm thấy không cần thiết phải duy trì nó nữa, thì bạn có thể xóa nó đi “cho đỡ chật đất”. Để làm điều này, thì bạn sẽ thêm -d giữa branch và tên nhánh. Tất nhiên, bạn nên nhảy qua nhánh khác trước. Cụ thể, nếu tôi muốn xóa luôn nhánh user-interface thì tôi làm như sau:

Tuy nhiên, nó không xóa ngay, mà sẽ hỏi lại là bạn có chắc chắn chưa, nhất là khi bạn chưa merge nhánh con vào nhánh master chính. Nếu chắc chắn rồi, hoặc bạn biết bạn đang làm gì và không muốn qua bước xác nhận kia, thì bạn có thể cho thực thi câu lệnh như bên dưới:

Mẹo: Cá nhân tôi thông thường, khi tạo branch mới cũng như xóa một branch không cần nữa, tôi hay nhảy về nhánh master.

4. Tổng hợp các branch phụ vào master branch:

Thực tế thì không nhất thiết bạn phải merge các branch phụ vào master branch, mà bạn có thể merge 2 branch phụ lại với nhau cũng được, và điều này rất thường xuyên xảy ra. Chẳng hạn như trong phân nhóm về giao diện vẫn có sự phân chia giữa các thành viên, và mỗi người có (ít nhất) 1 branch riêng. Ở đây tôi sẽ nói về master branch và bạn, như thường lệ, áp dụng vào tình huống bạn muốn.

Trước hết, chúng ta sẽ chuyển về branch đích, tức là branch sẽ nhận các commits từ các branches khác, trong trường hợp này là master branch:

Thao tác tiếp theo cũng đơn giản không kém, chỉ là nói cho Git biết là bạn sẽ merge branch nào vào branch đang đứng hiện tại. Vd tôi muốn merge user-interface vào master, thì tôi chỉ việc đánh vào dòng bên dưới và cho thực thi:

Tuy nhiên, trong một số tình huống cụ thể thì sự việc không hẳn sẽ tốt đẹp. Chẳng hạn, có nhiều người cùng sửa đổi nội dung của 1 file giữa lần merge trước và lần merge này, Git không tự động giải quyết được, và sẽ yêu cầu bạn tự xử lí trước. Và xử lí ra sao thì còn tùy vào thực tế của bạn. Ở đây, tôi sẽ bỏ qua phần giải quyết, giả sử là nhóm bạn đã thống nhất ý kiến với nhau, chốt lại rồi, thì cứ add lại tất cả các tập tin, và commit lại trước khi gộp nhánh.

Lưu ý là hoạt động gộp nhánh cũng được tính như một commit trên nhánh được gộp. Và cũng như các commits khác, bạn có thể thoải mái revert lại khi cần thiết.

Sang bài cuối cùng, tôi sẽ trình bày về thao tác đưa source lên các Git Repo Centers cũng như clone source có sẵn về. Hẹn gặp lại.

Leave a Reply

Your email address will not be published. Required fields are marked *

This site uses Akismet to reduce spam. Learn how your comment data is processed.