Cách gộp nhiều commit thành một với git rebase

Cách gộp nhiều commit thành một với git rebase

Trong thực tế, việc gộp nhiều commit thành một có lẽ là một công việc thường xuyên và cần phải làm đối với các anh em coder đang làm việc với GIT. Nếu bạn tự hỏi tại sao phải làm điều này, hãy tưởng tượng bạn đang làm một tính năng nào đó cho dự án, và vì lý do nào đó bạn phải thay đổi hay chỉnh sửa nó nhiều lần và mỗi lần như vậy bạn push lên một commit, như vậy có thể bạn sẽ phải có rất nhiều commit trên một branch. Và lịch sử sẽ có một cái nhìn lộn xộn như thấy này:

068c3d6 fix bug login 3
b45bfd8 fix bug login 2
682c63e fix bug login
4a12897 change style modal login
35de1dd Add modal login
f958619 change style part 4
8c27c9f change style part 3
e3e0627 change style part 2
9c6d775 change style
72e876d fix bug feature comment
2480819 fix bug feature like
0559dca Add feature like
e96cc5b Add feature comment
695c74f fix bug style
44af1f8 fix bug
5b15ac1 fix bug
8115521 Add index page
...

Lịch sử dài ngoằng với những commit vô nghĩa như thế này làm cho nhóm của bạn khó hiểu được mục đích chính của branch, và không những không được đẹp mắt, nó còn khiến chúng ta bị rối và có chút phức tạp hơn trong quá trình chúng ta merge nó vào branch chính và revert back nếu nhỡ branch này có vẫn đề chưa thể release được. Cho nên giải pháp hữu hiệu nhất là chúng ta gộp nhiều commit lại thành một bằng lệnh rebase. Làm như thế nào thì các bạn cùng làm theo các bước dưới đây nhé :).

1. Đầu tiên chúng ta dùng lệnh git log để xem lịch sử commit:

git log --oneline

sau khi dùng lệnh trên, lịch sử commit hiển thị như sau:

068c3d6 fix bug login 3
b45bfd8 fix bug login 2
682c63e fix bug login
4a12897 change style modal login
35de1dd Add modal login
f958619 change style part 4
8c27c9f change style part 3
e3e0627 change style part 2
9c6d775 change style
72e876d fix bug feature comment
2480819 fix bug feature like
0559dca Add feature like
e96cc5b Add feature comment
695c74f fix bug style
44af1f8 fix bug
5b15ac1 fix bug
8115521 Add index page
...

2. Tiếp theo chúng ta xác định số lượng commit mà các bạn muốn gộp thành một là dùng lệnh git rebase:

git rebase -i HEAD~3

Ở đây mình chỉ ví dụ 3 commit cho các bạn dễ nhìn, nếu bạn muốn gộp 4 commit gần nhất thì các bạn đổi thành git rebase -i HEAD~4, N commit thì đổi thành git rebase -i HEAD~N nhé. Sau khi dùng lệnh trên thì cửa sổ soạn thảo sẽ hiển thị như dưới:

pick 682c63e fix bug login
pick b45bfd8 fix bug login 2
pick 068c3d6 fix bug login 3

# Rebase 4a12897..068c3d6 onto 4a12897 (3 commands)
#
# Commands:
# p, pick = use commit
# r, reword = use commit, but edit the commit message
# e, edit = use commit, but stop for amending
# s, squash = use commit, but meld into previous commit
# f, fixup = like "squash", but discard this commit's log message
# x, exec = run command (the rest of the line) using shell
# d, drop = remove commit
#
# These lines can be re-ordered; they are executed from top to bottom.
#
# If you remove a line here THAT COMMIT WILL BE LOST.
#
# However, if you remove everything, the rebase will be aborted.
#
# Note that empty commits are commented out

3. Từ dòng thứ 2 các bạn thay từ pick thành s vào lưu lại như dưới:

pick 682c63e fix bug login
s b45bfd8 fix bug login 2
s 068c3d6 fix bug login 3

# Rebase 4a12897..068c3d6 onto 4a12897 (3 commands)
#
# Commands:
# p, pick = use commit
# r, reword = use commit, but edit the commit message
# e, edit = use commit, but stop for amending
# s, squash = use commit, but meld into previous commit
# f, fixup = like "squash", but discard this commit's log message
# x, exec = run command (the rest of the line) using shell
# d, drop = remove commit
#
# These lines can be re-ordered; they are executed from top to bottom.
#
# If you remove a line here THAT COMMIT WILL BE LOST.
#
# However, if you remove everything, the rebase will be aborted.
#
# Note that empty commits are commented out

4. Sau khi bạn lưu lại ở bước trên thì một cửa sổ soạn thảo nữa hiển thị để bạn thay đổi mô tả của commit được gộp này (Lúc đầu có 3 commit với 3 mô tả khác nhau, giờ chúng ta gộp chúng lại thành một thì chúng ta cần đổi một mô tả mới rõ ràng hơn đúng không nào?):

# This is a combination of 3 commits.
# This is the 1st commit message:

fix bug login

# This is the commit message #2:

fix bug login 2

# This is the commit message #3:

fix bug login 3

# Please enter the commit message for your changes. Lines starting
# with '#' will be ignored, and an empty message aborts the commit.
#
# Date:      Thu Feb 27 19:28:58 2020 +0700
#
# interactive rebase in progress; onto 4a12897
# Last commands done (3 commands done):
#    s b45bfd8 fix bug login 2
#    s 068c3d6 fix bug login 3
# No commands remaining.
# You are currently rebasing branch 'feature_top_page' on '4a12897'.
#
# Changes to be committed:
#       modified:   index.php
#

5. Tiếp theo chúng ta thay đổi mô tả commit bằng cách xoá các nội dung mô tả cũ và thay bằng mô tả mới như dưới và lưu lại:

# This is a combination of 3 commits.
# This is the 1st commit message:

Đây là mô tả mới của các commit được gộp nhé!!!

# fix bug login

# This is the commit message #2:

# fix bug login 2

# This is the commit message #3:

# fix bug login 3

# Please enter the commit message for your changes. Lines starting
# with '#' will be ignored, and an empty message aborts the commit.
#
# Date:      Thu Feb 27 19:28:58 2020 +0700
#
# interactive rebase in progress; onto 4a12897
# Last commands done (3 commands done):
#    s b45bfd8 fix bug login 2
#    s 068c3d6 fix bug login 3
# No commands remaining.
# You are currently rebasing branch 'feature_top_page' on '4a12897'.
#
# Changes to be committed:
#       modified:   index.php
#

Ở đây thay vì mình xoá đi các dòng mô tả cũ, thì chỉ chỉ cần thêm dấu # ở trước các dòng đó cho nhanh nhé, bởi vì ở đây, các dòng có dấu # ở trước sẽ được hệ thống bỏ qua xem như nó không thấy dòng đó lúc thực thi nhé :). 

Sau khi lưu xong, các bạn thử kiểm tra lại bằng lệnh git log --oneline sẽ thấy như dưới:

bcf6692 Đây là mô tả mới của các commit được gộp nhé!!!
4a12897 change style modal login
35de1dd Add modal login
f958619 change style part 4
8c27c9f change style part 3
e3e0627 change style part 2
9c6d775 change style
72e876d fix bug feature comment
2480819 fix bug feature like
0559dca Add feature like
e96cc5b Add feature comment
695c74f fix bug style
44af1f8 fix bug
5b15ac1 fix bug
8115521 Add index page

Đấy, các bạn thấy chưa, 3 commit cũ đã được gộp lại thành một commit với mô tả mới rồi đúng không nào?.

6. Cuối cùng chúng ta push các thay đổi mới lên server. Lúc này chúng ta cần thêm option -f để GIT ghi đè lên các commit cũ ở trên server.

git push -f origin feature_top_page


Đôi lời chú ý:

Khi bạn làm việc với những tính năng nào đó trong dự án, chắc chắn bạn sẽ tạo ra nhiều commit khác nhau, không liên tục trong lịch sử git, Sẽ thuận tiện hơn rất nhiều nếu các bạn biết cách để gộp tất cả các commit của tính năng đó thành một commit duy nhất.

Việc gộp nhiều commit thành một giúp dễ đọc và làm sạch lịch sử của nhánh chính, mình tin chắc là hiện tại cũng có nhiều bạn đang dùng GIT nhưng không hề biết GIT có hỗ trợ tính năng này, hi vọng các bạn có thể đọc được bài này và sử dụng nó giúp giúp cho git log của dự án mình trở nên sạch đẹp và rõ ràng hơn. 

Quá trình gộp này khá nguy hiểm nếu nhánh làm việc của bạn đã được push lên remote trước đó, vì vậy tốt nhất là các bạn nên gộp trên local branch trước khi các bạn push lên remote. Còn nếu nhỡ các bạn đã push lên trước đó sau đó mới gộp các commit thì ở nơi nào đó muốn pull code mới của branch này các bạn không thể pull theo cách thông thường được vì chắc chắn sẽ gây ra conflict bởi vì history trên remote branch là local branch là khác nhau, các bạn có thể dùng git reset --hard origin/<branch_name>.

Hãy Like nếu bạn thấy thích bài viết này nhé :)
Hoàng Phi IT

Hoàng Phi IT.

Tác giả

Cảm ơn bạn rất nhiều vì đã đọc hết bài viết của mình, nếu bạn thấy nó hữu ích hay có bất kỳ ý kiến gì hãy comment bên dưới cho mình biết với nhé!. Cảm ơn bạn rất nhiều!!!!!!!!!