Menu
CoddyTech

Git: squash commit

Cập nhật lần cuối

Squash là gộp nhiều commit thành một, để một loạt commit lộn xộn kiểu "wip", "fix typo", "actually fix it" trở thành một commit gọn gàng duy nhất. Công cụ quen thuộc là rebase tương tác, git rebase -i, nơi bạn đánh dấu các commit cần gộp lại. Vì squash viết lại lịch sử, hãy làm trước khi push, hoặc trên một nhánh chỉ mình bạn làm.

Bạn có thể thử các lệnh này trong terminal playground: một shell thật ngay trên trình duyệt, không cần cài đặt gì.

Squash gộp một loạt commit nhỏ thành một commit gọn gàng bằng rebase tương tác.

Cú pháp

LệnhTác dụng
git rebase -i HEAD~3Rebase tương tác 3 commit gần nhất
git rebase -i mainRebase mọi commit kể từ main
git merge --squash featureGộp các commit của một nhánh thành một khi merge
git reset --soft HEAD~3 && git commitSquash 3 commit cuối mà không cần rebase

Lệnh trong rebase tương tác

Trong trình soạn thảo vừa mở, đổi pick thành một trong các từ khóa sau.

Từ khóaTác dụng
pickGiữ nguyên commit
squash (s)Gộp vào commit trước đó, nối các thông điệp
fixup (f)Gộp vào nhưng bỏ thông điệp của commit này
reword (r)Giữ commit nhưng sửa thông điệp

Ví dụ từng bước

Squash ba commit cuối thành một trước khi push.

BướcThao tácKết quả
1git rebase -i HEAD~3Mở 3 commit cuối trong trình soạn thảo
2Đổi commit 2 và 3 thành squashĐánh dấu để gộp chúng vào commit đầu tiên
3Lưu và sửa thông điệp đã gộpBa commit trở thành một commit gọn gàng

Câu hỏi thường gặp về squash commit trong Git

Squash commit nghĩa là gì?

Squash biến nhiều commit thành một commit chứa toàn bộ thay đổi của chúng. Các tệp cuối cùng vẫn y hệt; chỉ lịch sử thay đổi, nên người review thấy một commit với một thông điệp thay vì một chuỗi sửa lặt vặt.

Làm sao squash N commit cuối trong Git?
Chạy git rebase -i HEAD~N (ví dụ HEAD~3 cho ba commit cuối). Trong trình soạn thảo, để commit đầu tiên là pick và đổi các commit còn lại thành squash (hoặc fixup để bỏ thông điệp của chúng). Lưu lại, sửa thông điệp commit đã gộp, và các commit sẽ gộp thành một.
squash và fixup khác nhau thế nào?
Cả hai đều gộp một commit vào commit trước nó. squash giữ thông điệp của commit và cho bạn ghép nó với các thông điệp khác trong trình soạn thảo. fixup bỏ hẳn thông điệp của commit, chỉ giữ thông điệp của commit trước đó. Rất tiện cho những commit kiểu "oops, sửa nhỏ" mà bạn không muốn xuất hiện trong thông điệp cuối cùng.
Làm sao squash cả một nhánh khi merge?
Dùng git merge --squash feature, rồi git commit. Lệnh này áp dụng toàn bộ thay đổi của nhánh dưới dạng thay đổi đã stage và cho bạn ghi chúng thành một commit duy nhất trên nhánh đích, không mang theo từng commit riêng lẻ của nhánh. Nút "Squash and merge" của GitHub cũng làm đúng điều này.
Có squash được mà không cần rebase tương tác không?
Được. git reset --soft HEAD~N lùi nhánh N commit trong khi giữ mọi thay đổi của chúng ở trạng thái staged, rồi một lệnh git commit duy nhất ghi chúng thành một commit. Đây là cách nhanh để squash các commit gần nhất mà không phải mở trình soạn thảo rebase.
Có nên squash commit trước khi merge không?
Nhiều nhóm làm vậy, để mỗi tính năng vào nhánh chính dưới dạng một commit dễ đọc và dễ revert. Cái giá là mất lịch sử từng bước. Cứ thoải mái squash trên nhánh chỉ mình bạn dùng; với nhánh dùng chung, hãy thống nhất trước, vì commit bị viết lại buộc mọi người phải reset bản của họ.
Có thể luyện tập lệnh này online không?

Có. Mở terminal playground để chạy rebase tương tác trong một shell thật ngay trên trình duyệt, không cần cài đặt gì. Khóa học Git tương tác miễn phí của Coddy cũng hướng dẫn từng bước cách rebase và dọn dẹp lịch sử.

Hình minh họa các ngôn ngữ lập trình của Coddy

Học Git cùng Coddy

Bắt đầu