Khóa học
Kiểm soát phiên bản là một trong những khía cạnh quan trọng nhất của phát triển phần mềm hiện đại. Nó cho phép bạn theo dõi thay đổi, cộng tác hiệu quả và duy trì lịch sử mã nguồn. Trong số các công cụ hiện có, Git nổi bật là một trong những hệ thống được dùng rộng rãi nhất để quản lý thay đổi mã.
Như bạn sẽ thấy trong khóa học Giới thiệu về Git của chúng tôi, Git cung cấp tính năng tạo nhánh để bạn làm việc trên các tính năng hoặc bản sửa lỗi khác nhau mà không ảnh hưởng đến mã nguồn chính. Mặc dù việc tạo nhánh giúp phát triển linh hoạt hơn, nhưng đôi khi việc giữ các nhánh gọn gàng có thể là một thách thức. Đây là lúc Git rebase phát huy tác dụng.
Tìm hiểu về nhánh trong Git
Như chúng tôi trình bày trong hướng dẫn Git và GitHub, các nhánh cho phép bạn phát triển tính năng mới hoặc sửa lỗi độc lập với mã nguồn chính. Chúng cung cấp một môi trường tách biệt, nơi bạn có thể thay đổi mà không làm gián đoạn công việc đang diễn ra ở các nhánh khác.
Có một số luồng làm việc với nhánh thường gặp, bao gồm:
- Nhánh tính năng (feature branches): Dùng để phát triển tính năng mới trước khi hợp nhất vào nhánh chính.
- Nhánh phát hành (release branches): Dùng để ổn định mã trước một bản phát hành mới.
- Nhánh hotfix: Được tạo để khắc phục các sự cố nghiêm trọng.
Quản lý hiệu quả các nhánh này là điều then chốt để duy trì lịch sử mã nguồn sạch và có tổ chức.

Git Rebase là gì?
Git rebase là lệnh cho phép bạn di chuyển hoặc áp dụng lại các commit từ một nhánh lên một nhánh khác. Khác với merge, vốn tạo ra một commit mới để kết hợp thay đổi từ các nhánh, rebase áp dụng lần lượt các thay đổi lên nhánh đích. Kết quả là một lịch sử tuyến tính mà không có các commit merge không cần thiết.
Khi rebase, Git lấy từng commit từ nhánh nguồn và áp dụng lên trên commit mới nhất ở nhánh đích. Điều này giúp lịch sử commit dễ đọc và dễ theo dõi hơn. Chúng tôi nói thêm về cách xem toàn bộ lịch sử commit của một kho trong Hướng dẫn Git Diff.

Vì sao dùng Git Rebase?
Rebase hữu ích vì nhiều lý do:
- Tạo lịch sử commit tuyến tính. Thay vì có một lịch sử với nhiều commit merge, rebase giúp giữ log commit sạch và dễ hiểu.
- Cải thiện cộng tác và rà soát mã. Lịch sử commit rõ ràng giúp nhóm rà soát thay đổi hiệu quả hơn.
- Tránh commit merge không cần thiết. Bằng cách rebase thay vì merge, bạn có thể cập nhật nhánh mà không làm rối log commit.
Tuy nhiên, rebase có thể rủi ro, đặc biệt khi làm việc trên các nhánh dùng chung, vì nó ghi lại lịch sử commit và có thể gây xung đột hoặc khiến việc theo dõi thay đổi trở nên khó khăn. Tốt nhất là tránh rebase các nhánh công khai và sử dụng thận trọng trong quy trình cộng tác.
Khi nào nên dùng Git Rebase
Có một vài trường hợp mà dùng Git rebase là lựa chọn đúng. Chúng tôi đã phân tích chi tiết từng trường hợp bên dưới:
Rebase các nhánh tính năng cục bộ
Khi làm việc trên một nhánh tính năng, việc cập nhật nó với các thay đổi mới nhất từ nhánh chính là điều thường gặp. Rebase, vốn đặt các commit của nhánh tính năng lên trên nhánh chính mới nhất, giúp duy trì lịch sử commit sạch như một lựa chọn thay thế cho merge.
Giữ nhánh tính năng luôn cập nhật
Khi nhiều nhà phát triển cùng làm việc trên cùng một kho, nhánh chính thường xuyên thay đổi. Rebase giúp giữ nhánh tính năng được cập nhật mà không thêm các commit merge không cần thiết.
Rebase trong cộng tác nhóm
Khi làm việc theo nhóm, rebase có thể giúp ngăn ngừa xung đột trước khi chúng xảy ra. Bằng cách thường xuyên rebase nhánh tính năng lên nhánh chính, bạn có thể tích hợp thay đổi dần dần, giảm rủi ro xung đột khi merge về sau.
Hướng dẫn Git Rebase theo từng bước
Trong phần này, chúng tôi sẽ hướng dẫn bạn quy trình rebase với Git, cung cấp các bước chi tiết cho mọi thứ bạn cần biết.

Chuẩn bị trước khi rebase
Trước khi bắt đầu rebase, hãy đảm bảo thư mục làm việc sạch. Điều này có nghĩa là commit hoặc stash mọi thay đổi trước khi rebase.

Ngoài ra, hãy kiểm tra bạn đang ở đúng nhánh bằng cách chạy:
git branch
Lấy về (fetch) các thay đổi mới nhất
Trước khi rebase, hãy đảm bảo kho cục bộ có các thay đổi mới nhất từ kho từ xa:
git fetch origin
Chuyển sang nhánh tính năng
Chuyển sang nhánh tính năng cần rebase:
git checkout your-feature-branch
Rebase lên nhánh chính
Để áp dụng các commit của nhánh tính năng lên trên nhánh chính mới nhất, chạy:
git rebase main
Git sẽ áp dụng lại từng commit từ nhánh tính năng lên nhánh chính đã cập nhật.

Khi bạn chạy git rebase main, Git lấy các thay đổi từ nhánh chính và áp dụng chúng trước các commit của nhánh tính năng. Điều này giúp lịch sử của bạn sạch và tuyến tính. Quá trình này phát lại các commit của bạn lên trạng thái mới nhất của main, tạo ra một lịch sử dự án tuyến tính không có commit merge.
Ví dụ, giả sử nhánh chính có các commit A và B. Nhánh tính năng của bạn đã rẽ nhánh từ A và bao gồm các commit C và D.
A---B (main)
\
C---D (feature)
Sau git rebase main, nhánh tính năng của bạn được cập nhật để bao gồm các commit từ main, theo sau là các commit của bạn:
---B---C'---D' (feature)
Ở đây, C và D là các commit mới đại diện cho thay đổi gốc của bạn, nay được đặt trên B.
Giải quyết xung đột (nếu có)
Nếu xảy ra xung đột trong quá trình rebase, Git sẽ tạm dừng và cho phép bạn giải quyết chúng.
Đánh dấu xung đột đã được giải quyết sau khi bạn sửa xong:
git add .
git rebase --continue
Nếu cần, bạn có thể hủy rebase bằng:
git rebase --abort
Hoàn tất rebase
Sau khi rebase thành công, hãy xác minh nhánh và kiểm thử mã để đảm bảo mọi thứ hoạt động đúng.
Rebase tương tác trong Git
Ngoài kiểu rebase thông thường bạn đã làm ở phần trước, bạn cũng có thể rebase tương tác. Cách này cho bạn nhiều quyền kiểm soát hơn, như bạn sẽ thấy bên dưới.
Rebase tương tác là gì?
Rebase tương tác git rebase -i cho phép bạn chỉnh sửa các commit trước khi áp dụng chúng. Chế độ này cung cấp các tùy chọn như sắp xếp lại, chỉnh sửa, gộp (squash) và xóa commit.
Vì sao dùng rebase tương tác?
Rebase tương tác hữu ích khi bạn muốn tinh chỉnh lịch sử commit. Nó giúp gộp nhiều commit, chỉnh sửa thông điệp commit và loại bỏ các commit không cần thiết trước khi hợp nhất vào nhánh chính.
Các cách dùng phổ biến của rebase tương tác
- Sắp xếp lại commit. Thay đổi thứ tự commit để lịch sử rõ ràng hơn.
- Gộp nhiều commit. Kết hợp vài commit nhỏ thành một commit có ý nghĩa.
- Chỉnh sửa thông điệp commit. Sửa thông điệp commit trước khi đẩy thay đổi. Việc viết thông điệp commit phù hợp rất quan trọng để làm rõ điều gì đã được cập nhật trong mã, như chúng tôi minh họa trong hướng dẫn GIT Push và Pull.
Cách thực hiện rebase tương tác
Để bắt đầu rebase tương tác, chạy:
git rebase -i HEAD~n
Thay n bằng số lượng commit bạn muốn chỉnh sửa. Giao diện tương tác cho phép bạn chọn cách xử lý từng commit.
Thực tiễn tốt và những lưu ý
Khi rebase, điều quan trọng là tuân thủ một số thực tiễn tốt. Hãy cùng nói về một vài điểm trong phần này.
Tránh rebase các nhánh dùng chung
Rebase một nhánh mà người khác cũng đang làm có thể gây xung đột và nhầm lẫn. Nếu một nhánh dùng chung đã được đẩy lên, hãy tránh rebase nó.
Thường xuyên fetch và rebase
Giữ nhánh tính năng được cập nhật với các thay đổi mới nhất từ nhánh chính giúp ngăn ngừa xung đột và làm cho việc merge mượt mà hơn.
Sao lưu trước khi rebase
Vì rebase chỉnh sửa lịch sử commit, thực hành tốt là tạo bản sao lưu trước khi bắt đầu. Dùng git stash hoặc tạo một nhánh tạm thời có thể ngăn mất dữ liệu ngoài ý muốn.
Lỗi thường gặp và cách tránh
Hãy xem một số thách thức thường gặp khi rebase và cách tránh chúng.
Vô tình rebase một nhánh công khai
Rebase một nhánh đã được chia sẻ có thể tạo ra xung đột cho các cộng tác viên khác. Nếu điều này xảy ra, hãy dùng git reflog để khôi phục các commit bị mất.
Khó khăn khi giải quyết xung đột
Khi xảy ra xung đột, hãy dành thời gian giải quyết cẩn thận. Sử dụng các công cụ như git mergetool có thể giúp quy trình dễ dàng hơn.
Mất lịch sử commit
Nếu các commit biến mất sau khi rebase, hãy dùng git reflog để tìm và khôi phục chúng.
Kết luận
Git rebase là một công cụ mạnh mẽ để duy trì lịch sử commit sạch và cải thiện cộng tác. Bằng cách sử dụng đúng cách — tránh rebase các nhánh dùng chung, thường xuyên fetch cập nhật và sao lưu thay đổi — bạn có thể tinh gọn quản lý phiên bản và giảm xung đột khi merge.
Hãy áp dụng những kỹ thuật này để giữ kho của bạn gọn gàng và quy trình làm việc hiệu quả. Muốn nâng cao chuyên môn Git? Hãy xem khóa học Git Trung cấp để khám phá các nền tảng của Git cho quản lý phiên bản trong dự án phần mềm và dữ liệu của bạn.
Câu hỏi thường gặp về Git Rebase
Sự khác nhau giữa Git rebase và Git merge là gì?
Git merge tạo một commit mới kết hợp các thay đổi từ hai nhánh, giữ nguyên lịch sử của cả hai. Ngược lại, Git rebase di chuyển các commit từ một nhánh và áp dụng chúng tuần tự lên nhánh khác, tạo ra lịch sử commit tuyến tính mà không có các commit merge thừa.
Khi nào tôi nên dùng Git rebase thay vì Git merge?
Hãy dùng Git rebase khi bạn muốn duy trì lịch sử commit sạch và tuyến tính, đặc biệt cho các nhánh tính năng. Nó đặc biệt hữu ích trước khi hợp nhất một nhánh tính năng vào nhánh chính để tránh các commit merge không cần thiết. Tuy nhiên, tránh rebase các nhánh dùng chung, vì nó có thể ghi lại lịch sử commit và gây vấn đề cho cộng tác viên.
Điều gì xảy ra nếu tôi gặp xung đột khi Git rebase?
Nếu xảy ra xung đột trong lúc rebase, Git sẽ tạm dừng và nhắc bạn giải quyết xung đột. Bạn cần sửa thủ công các tệp bị xung đột, đưa chúng vào staged với git add ., rồi tiếp tục rebase bằng git rebase --continue. Nếu xung đột quá phức tạp, bạn có thể hủy rebase bằng git rebase --abort và làm lại từ đầu.
Có an toàn không khi rebase một nhánh đã được đẩy lên kho từ xa?
Không, rebase một nhánh đã được đẩy và chia sẻ với người khác có thể gây ra vấn đề vì nó ghi lại lịch sử commit. Nếu buộc phải rebase một nhánh dùng chung, hãy trao đổi với nhóm và dùng git push --force-with-lease một cách cẩn trọng để tránh ghi đè thay đổi của người khác.
Làm thế nào để hoàn tác Git rebase nếu có sự cố?
Nếu bạn nhận ra rebase gây ra vấn đề, bạn có thể dùng git reflog để tìm commit trước khi rebase và khôi phục nó bằng git reset --hard <commit-hash>. Một lựa chọn khác là dùng git rebase --abort nếu rebase vẫn đang diễn ra và chưa hoàn tất.