Bài git-06 giới thiệu rebase để phát lại commit lên nhánh khác. git rebase -i (interactive) mạnh hơn hẳn: nó cho bạn viết lại lịch sử N commit gần nhất theo ý muốn — gộp nhiều commit thành một, sửa message, xóa commit thừa, đổi thứ tự. Đây là công cụ để dọn nhánh tính năng cho sạch trước khi mở PR: thay vì một chuỗi "wip", "fix typo", "sua nua", reviewer thấy một (hoặc vài) commit gọn gàng có nghĩa. Đo thật bằng git 2.39, tự động hóa để không cần mở editor.
Todo list của rebase tương tác
git rebase -i HEAD~N mở một "todo list" — mỗi commit một dòng, bắt đầu bằng một lệnh bạn có thể đổi:
pick giữ commit như cũ
reword giữ thay đổi, SỬA message
squash gộp vào commit phía trên, GỘP cả message (mở editor)
fixup gộp vào commit phía trên, BỎ message của nó (gọn hơn squash)
edit dừng lại để sửa nội dung commit đó
drop xóa hẳn commit; đổi thứ tự = đổi thứ tự các dòng
Lưu lại và đóng editor, Git thực thi từng dòng. Để tự động hóa (không mở editor tay), đặt GIT_SEQUENCE_EDITOR để sửa todo bằng script:
GIT_SEQUENCE_EDITOR='sed -i -e "2,\$s/^pick/fixup/"' git rebase -i HEAD~4
git rebase --autosquash # gộp tự động các commit đánh dấu fixup!/squash!

Hình 1: git rebase -i HEAD~N mở todo list; đổi pick thành reword/squash/fixup/edit/drop hay đổi thứ tự dòng để viết lại lịch sử. Tự động hóa bằng GIT_SEQUENCE_EDITOR/--autosquash. Quy tắc vàng: chỉ rebase commit chưa push chung.
Đo thật: 5 commit lộn xộn gộp còn 2

Hình 2: Trước có 5 commit (base + 4 cho tính năng X). rebase -i HEAD~4 với fixup gộp 3 commit "fix" vào commit đầu → còn 2 commit (aac45b5 + base). File vẫn đủ base a b c d — chỉ lịch sử gọn lại. reword đổi message thành feat: hoan thien tinh nang X.
Kết quả rõ ràng:
- Trước: 5 commit —
baserồithem tinh nang X,fix typo,fix typo nua,hoan thien X. Lịch sử điển hình của một buổi code: một commit chính + mấy commit sửa vặt. - fixup gộp lại:
GIT_SEQUENCE_EDITORđổi 3 dòngpickcuối thànhfixup, rebase gộp chúng vào commit đầu. Kết quả còn 2 commit (aac45b5 them tinh nang X+base). Dùngfixup(khôngsquash) nên không cần sửa message — message của các commit fix bị bỏ, giữ message commit đầu. - Nội dung nguyên vẹn:
cat f.txtvẫn chobase a b c d— mọi thay đổi còn đủ, chỉ lịch sử gọn lại. Rebase viết lại cách các commit được nhóm, không mất công việc. - reword: đổi message commit mới nhất thành
feat: hoan thien tinh nang X(SHA đổi thànhf693dd9vì message là một phần của commit — như bài git-01) mà nội dung không đổi.
Đánh đổi và lưu ý
Quy tắc vàng (nhắc lại từ git-06): chỉ rebase commit chưa push chung. Rebase tương tác viết lại SHA của mọi commit nó chạm tới. Nếu bạn rebase các commit đã push và người khác đã pull, lịch sử phân kỳ — lần push sau phải --force (nên dùng --force-with-lease) và đồng đội gặp rối. Chỉ dọn lịch sử nhánh riêng của mình trước khi mở PR, đừng đụng commit đã lên nhánh chung.
--autosquash + commit --fixup là quy trình chuyên nghiệp. Khi đang code, thay vì "fix typo", hãy git commit --fixup=<sha commit cần sửa> — Git tạo commit đánh dấu fixup!. Sau đó git rebase -i --autosquash tự sắp và gộp chúng vào đúng commit gốc. Sạch, ít thao tác tay, ít nhầm.
Gặp xung đột thì giải rồi --continue. Rebase phát lại từng commit; nếu một commit xung đột với thay đổi mới, rebase dừng — giải xung đột, git add, rồi git rebase --continue (hoặc --abort để hủy về trạng thái cũ). Với chuỗi dài, xung đột có thể lặp lại; git rerere (bài sau nếu có) giúp nhớ cách giải.
Đừng rebase quá tay thành "che giấu". Lịch sử sạch tốt, nhưng đừng gộp mọi thứ thành một commit khổng lồ — mất khả năng bisect/revert từng phần. Nguyên tắc: mỗi commit là một thay đổi logic hoàn chỉnh, tự biên dịch được. Dọn cho rõ ý, không phải cho ít commit nhất.
Ba ý mang về
git rebase -iviết lại N commit gần nhất qua todo list:pick/reword/squash/fixup/edit/drop/đổi thứ tự — đo thật, 5 commit lộn xộn gộpfixupcòn 2 commit sạch, nội dung file (base a b c d) nguyên vẹn.- Tự động hóa bằng
GIT_SEQUENCE_EDITOR/--autosquash: dùnggit commit --fixup=<sha>khi code rồirebase -i --autosquashđể gộp đúng chỗ;fixupgọn hơnsquash(bỏ message thừa). - Quy tắc vàng: chỉ rebase commit chưa push chung (viết lại SHA → nhánh chia sẻ phân kỳ); giải xung đột rồi
--continue/--abort; và dọn cho rõ ý — mỗi commit một thay đổi logic hoàn chỉnh, đừng gộp thành một khối khổng lồ.
Nguồn
- Pro Git — Git Tools: Rewriting History (rebase -i, squash, autosquash): https://git-scm.com/book/en/v2/Git-Tools-Rewriting-History
- Git Documentation — git-rebase (mục Interactive Mode): https://git-scm.com/docs/git-rebase#_interactive_mode
Phần sau — bài cuối sê-ri Git — ta nhìn vào cách Git tự bảo trì kho: git gc, git prune, git fsck — dọn object mồ côi, nén packfile, và tìm lại thứ tưởng đã mất.