Làm chủ Git Rebase –onto trong 5 phút
Bạn đã bao giờ lỡ code nhánh feature-B dựa trên feature-A, để rồi nhận ra feature-A bị hủy hoặc quá rối rắm chưa? Lúc này, bạn chỉ muốn nhặt riêng các commit của mình sang main mà không muốn dính dáng gì đến đống hỗn độn ở nhánh cũ. Đừng ngồi gõ cherry-pick từng cái, git rebase --onto sẽ giúp bạn giải quyết trong một nốt nhạc.
Gặp tình huống này, hãy nhớ ngay cú pháp “thần thánh”:
bash
git rebase --onto <nhánh-đích> <nhánh-nguồn-cũ> <nhánh-hiện-tại>
Giả sử bạn đang ở feature-B và muốn chuyển thẳng lên main, bỏ qua feature-A:
bash
git rebase --onto main feature-A feature-B
Bạn có thể hiểu lệnh này là: “Lấy phần code của feature-B (loại trừ những gì đã có trong feature-A), rồi đặt chúng lên đỉnh của main”. Chỉ với một dòng lệnh, lịch sử Git của bạn sẽ mượt mà như chưa từng có cuộc chia ly.
Giải mã cơ chế hoạt động của –onto
Tại sao lệnh này lại mạnh mẽ đến vậy? Bí mật nằm ở cách Git chọn lọc commit. Trong khi rebase thông thường sẽ bê nguyên cả nhánh, --onto cho phép bạn xác định chính xác một khoảng commit để di chuyển.
Cấu trúc chi tiết bao gồm ba thành phần:
- newbase: Điểm dừng chân mới (nơi bạn muốn đặt các commit lên).
- upstream: Điểm mốc để Git xác định phần thừa cần cắt bỏ. Git sẽ bỏ qua mọi thứ từ mốc này trở về trước.
- branch: Nhánh bạn muốn di chuyển (không bắt buộc nếu bạn đang đứng ở chính nhánh đó).
Nhiều bạn thường chọn cách thủ công là cherry-pick từng commit một. Cách này không sai, nhưng nếu bạn có khoảng 15-20 commit thì việc này cực kỳ tốn thời gian và rất dễ nhầm lẫn mã hash.
Kịch bản thực tế: Khi các tính năng chồng chéo
Thử đặt mình vào một sơ đồ commit quen thuộc như sau:
o---o---o (main)
\
o---o (feature-A)
\
o---o---o (feature-B)
Bối cảnh: feature-A vẫn đang dang dở, nhưng sếp yêu cầu bạn đưa feature-B lên main gấp để demo cho khách hàng. Nếu dùng rebase main thông thường, Git sẽ kéo theo cả đống code lỗi từ feature-A vào main. Thảm họa là đây!
Giải pháp với --onto:
bash
git rebase --onto main feature-A feature-B
Kết quả nhận được:
o---o---o (main)
| \
| o'---o'---o' (feature-B mới mọc ra từ main)
\
o---o (feature-A cũ vẫn nằm yên một chỗ)
Nhánh feature-B lúc này đã hoàn toàn sạch bóng dấu vết của feature-A. Đây là cách tốt nhất để bạn làm sạch lịch sử commit trước khi tạo Pull Request gửi cho Leader review.
Kỹ thuật nâng cao: Xóa commit lỗi ở giữa nhánh
Một công dụng cực hữu ích khác là xóa một nhóm commit nằm giữa chừng mà không cần dùng rebase -i. Giả sử bạn có chuỗi commit A -> B -> C -> D -> E, nhưng commit B và C lỡ chứa API Key hoặc mật khẩu nhạy cảm.
bash
git rebase --onto <hash-của-A> <hash-của-C> master
Lệnh này bảo Git: “Hãy lấy các commit sau C (tức là D và E), rồi nối chúng trực tiếp vào A“. Bạn vừa loại bỏ được dữ liệu nhạy cảm chỉ trong vài giây.
Kinh nghiệm xương máu và lưu ý an toàn
Sử dụng rebase đồng nghĩa với việc bạn đang viết lại lịch sử (rewrite history). Hãy khắc cốt ghi tâm một quy tắc: Không bao giờ rebase trên những nhánh đã push lên server và có người khác đang làm chung.
Nếu bắt buộc phải push sau khi rebase, hãy tập thói quen dùng:
bash
git push --force-with-lease
Lệnh này an toàn hơn --force vì nó sẽ từ chối nếu server có commit mới mà bạn chưa cập nhật. Nó giúp bạn tránh việc vô tình ghi đè lên công sức của đồng nghiệp – một sai lầm cực kỳ phổ biến khi làm việc nhóm.
Mẹo nhỏ: Trước khi thực hiện bất kỳ lệnh Git phức tạp nào, hãy tạo một nhánh dự phòng bằng git branch backup-branch. Nếu có lỡ tay làm hỏng, bạn chỉ việc xóa nhánh lỗi và đổi tên nhánh backup lại là xong. An toàn là trên hết!
Tóm tắt các bước xử lý
- Xác định 3 điểm: Đích đến (newbase), mốc cần cắt (upstream) và nhánh cần dời.
- Tạo nhánh backup để đảm bảo đường lui.
- Chạy lệnh
git rebase --onto. - Giải quyết xung đột (conflict) nếu có. Việc xung đột khi chuyển sang nền code mới là hoàn toàn bình thường.
- Kiểm tra lại thành quả bằng
git log --oneline --graph. - Push lên với
--force-with-lease.
Hy vọng hướng dẫn này giúp bạn tự tin hơn khi xử lý những cấu trúc nhánh phức tạp. git rebase --onto không hề khó, nó chỉ yêu cầu bạn tư duy rõ ràng về việc “cắt từ đâu” và “dán vào đâu”. Chúc các bạn có những commit thật sạch đẹp!

