Git: merge – rebase và những lưu ý

Bài viết được sự cho phép của tác giả Tùng Nguyễn

Merge và Rebase

Sau một vài năm sử dụng Git, tôi càng ngày càng “lún sâu” vào Git commands (không phải xài git bằng command line). Trong quá trình làm việc với các team đông anh em, tôi tìm thấy lệnh git rebase. Khá hay và ngay lập tức tôi áp dụng nó vào đời sống coding của tôi, nhưng sau một thời gian sử dụng tôi nhận ra rebasing thật sự không phù hợp cho người mới bắt đầu xài git. Hôm bữa có anh em hỏi tôi git rebase là gì và khi nào xài và xài nó như thế nào!?

Trong bài viết này tôi chia sẻ với anh em git rebase là gì, nó khác gì với git merge và những lưu ý khi sử dụng git rebase.

Merge và Rebase

Về cơ bản anh em có thể hiểu git rebase tương tự như git merge. Nó đều dùng để kết hợp những thay đổi từ nhánh này qua nhánh kia, nhưng chỉ khác nhau về cơ chế hoạt động.

Bây giờ lấy ví dụ tôi đang làm việc trên nhánh #feature-a, commit cật lực lên đó. Cùng lúc đó team member của tôi push commit lên nhánh main. Các bạn nhìn hình dưới cho dễ hình dung:

Merge và Rebase

Bây giờ giả sử những commit trên nhánh main có liên quan đến #feature-a mà tôi đang làm. Tôi muốn kết hợp mấy commit đó vào nhánh #feature-a thì sẽ có 2 cách làm: merging hay rebasing.

Git merge

Để merge 2 nhánh lại với nhau tôi nghĩ anh em ai cũng biết. Có thể chạy 2 câu lệnh đơn giản sau:

git checkout #feature-a

git merge main

Hoặc đơn giản hơn nữa khi bạn xài UI tool như SourceTree hay GitKraken, anh em làm như sau, tôi thì đang xài GitKraken:

Merge và Rebase

Khi anh em làm vậy, git sẽ tạo 1 “merge commit” mới trên nhánh #feature-a, trong đó chứa tất cả các commit của 2 nhánh, bây giờ cấu trúc của 2 nhánh main và #feature-a giống giống như vầy:

Merge và Rebase

Git merge dễ sử dụng và an toàn vì logic của nó không làm phá hủy cấu trúc lịch sử của các nhánh. Các lịch sử commit trên nhánh main và #feature-a sẽ không bị thay đổi.

Mặt khác, nhánh #feature-a luôn luôn có 1 “merge commit” mới mỗi khi anh em merge nó với nhánh khác. Trong trường hợp nhánh main được merge vào liên tục, điều này sẽ làm git của tôi rối mù lên, tôi nói riêng và team member nói chung sẽ rất khó hiểu được lịch sử commit của cả project.

  Những lệnh GIT thường sử dụng từ cơ bản đến nâng cao

  Biến Git và GitHub trở thành công cụ đắc lực cho Software Engineer

Git rebase

Như 1 biện pháp thay thế cho git merge, anh em có thể xài git rebase nhánh #feaure-a trên nhánh main sử dụng command như sau:

Merge và Rebase

git checkout #feature-a

git rebase main

Hoặc xài UI tool như SourceTree hay GitKraken như sau:

Git rebase sẽ đem hết commit của nhánh #feature-a lên đầu của nhánh main, bao gồm cả những commit hiện có trên nhánh main luôn. Nhưng thay vì tạo ra 1 cái “merge commit” như git mergegit rebase sẽ “viết lại lịch sử” commit của project bằng cách tự động tạo các commit mới dựa trên các commit trên nhánh #feature-a.

Merge và Rebase

Lợi ích chính của việc xài git rebase là đem lại cho chúng ta 1 project có lịch sử commit rất đẹp và gọn gàng, không rối mù với các nhánh chỉa qua chỉa lại như git merge. Nó cũng sẽ loại bỏ được những “merge commit” không cần thiết của git merge. Nhìn vào sơ đồ ở trên ta có thể thấy project trở nên thằng như ruột ngựa, git log hay git bisect nhìn cũng rất rõ ràng, sạch sẽ.

Tham khảo Job FrontEnd HOT trên TopDev!

Những lưu ý khi sử dụng Rebasing

Một khi anh em đã hiểu được git rebase là gì và cơ chế hoạt động của nó. Việc chúng ta cần chú ý nhất ở đây là khi nào nên sử dụng git rebase.

Nguyên tắc vàng mà tôi đúc kết được là không được sử dụng git rebase lên “public branch”, tức là mấy nhánh như develop hay main.

Bây giờ lấy ví dụ, tôi sử dụng git rebase nhánh main lên nhánh #feature-a của tôi, git history của tôi sẽ giống giống hình dưới đây:

Merge và Rebase

Rebase sẽ đem hết commit của nhánh main lên đầu nhánh #feature-a. Nhìn thì thấy cũng bình thường, nhưng nghĩ lại thì tôi nhận ra nó chỉ đúng ở repo local của tôi thôi. Team member của tôi đều đang làm việc trên nhánh original main. Vì rebase sẽ tạo ra các commit hoàn toàn mới nên git sẽ hiểu là nhánh main của tôi khác hoàn toàn với nhánh main của những người khác.

Bây giờ điều duy nhất có thể làm là merge 2 nhánh main lại với nhau, điều này dẫn đến tạo ra thêm 1 merge commit và 1 nùi những commit với thay đổi giống nhau ( các commit ở nhánh main cũ, và commit ở nhánh rebase của tôi).

Bởi vậy khi anh em đang định sử dụng git rebase, hãy dừng lại 1 chút và tự trả lời câu hỏi “Liệu có ai đang làm việc trên nhánh này không!?”. Nếu có, tôi đề nghị anh em hãy bỏ ý định sử dụng git rebase lên nhánh đó. Còn nếu không, anh em thoải mái viết lại lịch sử của mình.

Lúc này nếu tôi lười quá, muốn force push nhánh main của mình lên remote cho nhanh, git sẽ la làng vì làm thế có thể sẽ tạo rất nhiều conflict. Nhưng tôi hoàn toàn có thể “cưỡng ép” git bằng cách thêm –force vào command:

git push --force

Làm thế sẽ giúp tôi nhẹ lòng nhưng team member của tôi thì không. Họ sẽ không hiểu chuyện gì đang xảy ra với nhanh main, mọi commit đều trở nên xa lạ.

Một lưu ý nữa là nếu anh em đang làm việc trên nhánh mà mình đã pushed một vài commit lên remote. Ví dụ anh em đang làm việc trên nhánh #feature-a, mà trước đó đã pushed vài commit lên remote rồi, thì anh em không nên rebase lên nhánh #feature-a.

Trên này là một vài chia sẻ của tôi về git base và những lưu ý khi sử dụng nó. Hy vọng anh em nào chưa biết có thêm 1 chút kinh nghiệm về git của mình.

Happy hacking

Bài viết gốc được đăng tải tại omatsuri.blog, biết thêm về tác giả tại LinkedIn

Xem thêm:

Tìm việc làm IT mới nhất trên TopDev