Nhánh Git: trực giác và thực tế
(jvns.ca)- Nhiều người cho rằng cách hoạt động của Git branch không mang tính trực quan.
- Bài viết giải thích sự khác biệt giữa mô hình trực quan phổ biến về Git branch và cách branch thực sự được biểu diễn bên trong Git.
- Bài viết cho thấy mô hình trực quan và cách Git thực sự hoạt động trên thực tế có liên hệ rất chặt chẽ với nhau.
- Thảo luận về những giới hạn của mô hình trực quan và lý do nó có thể gây ra vấn đề.
Mô hình branch trực quan
- Nhiều người hình dung branch như 'cành của cây táo'.
- Trong Git, branch không có khái niệm 'cha', nên khác với cách nghĩ rằng nó được tách ra từ
main.
Trong Git, branch là toàn bộ lịch sử
- Trong Git, branch không chỉ là các commit được tách nhánh mà bao gồm toàn bộ lịch sử của mọi commit trước đó.
- Thông qua một repository ví dụ, bài viết cho thấy cả
mainvàmybranchđều có 4 commit.
Branch được lưu bằng ID commit
- Bên trong Git, branch được lưu dưới dạng một tệp văn bản nhỏ chứa ID commit.
- Commit mới nhất của mỗi branch được ghi trong tệp đó.
- Vì không có quan hệ cha-con giữa các branch, Git không biết mối quan hệ giữa các branch.
Trực giác của mọi người thường không hẳn là sai
- Nói rằng trực giác của mọi người về Git là 'sai' thì hơi ngớ ngẩn.
- Ngay cả một mô hình 'sai' trên thực tế vẫn có thể hữu ích.
Rebase cũng dùng khái niệm branch 'trực quan'
- Rebase chỉ áp dụng lại lên
maincác commit thuộc branch 'trực quan'. - Kết quả của rebase phù hợp với mô hình trực quan.
Merge cũng dùng khái niệm branch 'trực quan'
- Merge không sao chép commit, nhưng cần một commit nền tảng dùng chung.
- Merge base tìm ra commit nơi branch được tách ra dựa trên mô hình trực quan.
Pull request trên GitHub cũng dùng ý tưởng trực quan
- Khi tạo một pull request để merge
mybranchvàomaintrên GitHub, chỉ các commit thuộc branch trực quan mới được hiển thị.
Trực giác là tốt nhưng có giới hạn
- Định nghĩa branch theo trực giác khá khớp với công việc thực tế trong Git, nhưng Git không thể tự nhận biết branch nào được tách ra từ
main.
Trunk và branch được tách ra
- Mọi người nhận thức
mainvàmybranchtheo cách khác nhau, và điều này ảnh hưởng đến cách họ dùng Git. - Git không phân biệt được một branch có phải là 'nhánh tách ra' từ branch khác hay không.
Git có thể rebase theo 'chiều ngược lại'
- Vì Git không cho biết branch nào là 'nhánh tách ra' của branch khác, người dùng phải tự biết khi nào cần rebase branch nào.
- Cả
git rebase mainlẫn kiểu rebase ngượcgit rebase mybranchđều khả thi. Merge cũng vậy.
Việc thiếu cấu trúc phân cấp giữa các branch trong Git hơi kỳ lạ
- Câu nói branch
mainkhông hề đặc biệt xuất phát từ việc Git không nhận biết được quan hệ giữa các branch. - Giữa các branch có quan hệ với nhau, nhưng Git thì không biết gì cả.
UI branch của Git cũng hơi kỳ lạ
- Khi chỉ muốn xem các commit 'được tách nhánh', cách dùng
git logvàgit difflại khác nhau.
Trên GitHub, branch mặc định là đặc biệt
- GitHub có một 'branch mặc định', và branch này đóng vai trò đặc biệt.
Ý kiến của GN⁺
Điều quan trọng nhất trong bài này là hiểu được sự khác biệt giữa cách mọi người trực giác hóa Git branch và cách Git thực sự hoạt động. Bài viết sẽ giúp các kỹ sư phần mềm mới vào nghề hiểu rõ hơn về khái niệm Git branch và sử dụng nó hiệu quả hơn. Việc tìm hiểu mô hình trực quan của Git branch khớp với công việc thực tế như thế nào, cũng như cách Git không xử lý quan hệ giữa các branch, vừa thú vị vừa hữu ích.
1 bình luận
Ý kiến trên Hacker News
git reset --hardvàgit stashđể thao tác thay đổi và con trỏ branch. Để hủy một lần merge sai, tôi dùnggit reset --hard <commit cuối cùng trước khi merge>, và để áp dụng những chỉnh sửa nhỏ trên branch cục bộ sang branch chính, tôi dùnggit stash, sau đó checkout sang branch chính rồi dùnggit stash apply.git addvàgit commit. Hướng dẫn này trực quan hóa branch để giúp người đọc dễ hiểu hơn.git merge my-branchlà merge my-branch vào branch hiện tại, còngit rebase my-branchlà rebase branch hiện tại lên trên my-branch.main.git range-diff, bạn cũng cần lưu ý tới nền tảng. Công cụ này so sánh hai phạm vi nhưmain..previousvàmain..current.