Bài viết này mình sẽ chia sẻ cách revert một số commit cụ thể trong Git, giữ nguyên các commit khác, đồng thời đảm bảo tuân thủ quy trình bảo vệ nhánh (branch protection) nếu có.
Ở 2 phần trước về series sử dụng Git trong thực tế anh em đã cùng nhau tìm hiểu cơ bản về các trường hợp sử dụng Git và sự khác nhau giữa Git merge và git Rebase:
- Phần 1 - Các Trường Hợp Sử Dụng Git Nâng Cao Trong Thực Tế
- Phần 2 - Sự khác nhau giữa Git Merge và Git Rebase
Vậy hôm này anh em mình cùng tiếp tục tìm hiểu về một case cũng rất hay sử dụng trong công việc hàng ngày đó là revert code.
Trong quá trình làm việc thực tế, sẽ có lúc anh em gặp tình huống cần revert (hoàn nguyên) một số commit cụ thể hoặc code đã merge vào developmet hay release rồi mà có vấn đề cần phải revert tính năng đó. Chuyện này thường xảy ra khi một tính năng mới gặp vấn đề, và team quyết định tạm bỏ tính năng đó mà không ảnh hưởng đến những tính năng khác đang chạy ổn định. Vậy làm sao để revert những commit này một cách chính xác và không gặp lỗi?
Tình Huống Ví Dụ:
Giả sử anh em có một lịch sử commit như sau:
A B C D E F G H
B
,E
, vàG
là các commit liên quan đến tính năng mới (feature) cần revert vì lỗi.
- Các commit khác như
A
,C
,D
,F
,H
là của các tính năng khác đang hoạt động bình thường, cần được giữ lại.
Trong trường hợp nhánh development
và release
của dự án là protect branch không mình không thể push trực tiếp lúc nào cũng phải tạo PR/MR trước rồi cả team review rồi mới được merge. Để giải quyết, có hai cách phổ biến: revert từng commit hoặc revert merge commit của PR.
Trường Hợp 1: Revert Từng Commit
Nếu tính năng mới được đẩy lên thông qua nhiều commit riêng lẻ, anh em sẽ cần revert từng commit cụ thể.
Các Bước:
1. Tạo một nhánh hotfix: Để giữ nguyên nhánh release
và tuân thủ quy định bảo vệ nhánh, anh em cần tạo nhánh mới để tiến hành revert.
git checkout release
git pull origin release # Cập nhật nhánh release mới nhất
git checkout -b hotfix/revert-specific-commits
2. Revert từng commit: Sử dụng lệnh git revert
để revert các commit cần xóa.
git revert <commit-hash-B> # Revert commit B
git revert <commit-hash-E> # Revert commit E
git revert <commit-hash-G> # Revert commit G
Ví dụ:
git revert abc123 # Giả sử abc123 là hash của commit B git revert def456 # Giả sử def456 là hash của commit E git revert ghi789 # Giả sử ghi789 là hash của commit G
3. Xử lý editor sau khi revert: Khi chạy lệnh git revert
, Git sẽ mở một trình soạn thảo văn bản (editor) với thông tin về commit mà anh em đang revert. Thông thường, trình soạn thảo mặc định là vi
hoặc nano
, nhưng có thể là một trình khác tùy thuộc vào cấu hình của anh em.
Trong editor, dòng đầu tiên sẽ là thông điệp của commit revert, thường có dạng:
Revert "commit message gốc"
This reverts commit <commit-hash>.
- Nếu muốn chỉnh sửa thông điệp: Anh em có thể chỉnh sửa ngay trong trình soạn thảo.
- Nếu không muốn chỉnh sửa: Để nguyên và lưu lại.
Cách lưu:
- Trong
vi
:
- Nhấn
Esc
để thoát khỏi chế độ chỉnh sửa.
- Gõ
:wq
và nhấnEnter
để lưu và thoát.
- Trong
nano
:
- Nhấn
Ctrl + O
để lưu, rồi nhấnEnter
.
- Nhấn
Ctrl + X
để thoát.
4. Giải quyết xung đột nếu có: Nếu các commit cần revert gây ra xung đột với những commit khác, anh em sẽ cần giải quyết xung đột thủ công, sau đó tiếp tục quá trình revert.
Để tiếp tục sau khi giải quyết xung đột:
git add <các-file-bị-xung-đột>
git commit --continue # Hoàn tất revert sau khi xử lý xung đột
5. Đẩy nhánh hotfix lên remote: Sau khi hoàn tất, đẩy nhánh hotfix lên remote.
git push origin hotfix/revert-specific-commits
6. Tạo Pull Request: Vào hệ thống quản lý mã nguồn (GitHub, GitLab, Bitbucket, v.v.), tạo pull request từ nhánh hotfix để merge vào nhánh release
.
Trường Hợp 2: Revert Merge Commit của Pull Request
Nếu tính năng được merge vào nhánh release
qua một Pull Request duy nhất, thì thay vì revert từng commit, anh em có thể revert toàn bộ PR chỉ với một lệnh, nhanh hơn nhiều.
Các Bước:
1. Xác định merge commit của PR: Sử dụng lệnh git log
để tìm merge commit của PR đã merge vào nhánh release
. Merge commit thường có thông báo kiểu "Merge pull request #<PR-number> from <branch-name>".
git log --oneline
Ví dụ, merge commit có thể trông như sau:
abc1234 Merge pull request #15 from feature/your-feature
2. Revert merge commit: Sử dụng lệnh git revert
với tùy chọn -m
để chỉ định cha đầu tiên (thường là nhánh release
), và revert lại toàn bộ PR.
git revert -m 1 <merge-commit-hash>
Ví dụ:
git revert -m 1 abc1234
Lệnh này sẽ tạo một commit mới để hoàn nguyên tất cả thay đổi từ PR đã merge.
3. Xử lý editor sau khi revert: Giống như ở trường hợp trước, Git sẽ mở trình soạn thảo để xác nhận thông điệp commit revert. Anh em chỉ cần lưu lại và thoát ra, không cần chỉnh sửa nếu không cần thiết.
4. Giải quyết xung đột nếu có: Giống như cách trên, nếu gặp xung đột, anh em cần xử lý chúng trước khi tiếp tục.
5. Đẩy nhánh hotfix lên remote: Sau khi revert xong, đẩy nhánh lên remote.
git push origin hotfix/revert-merge
6. Tạo Pull Request: Tạo PR từ nhánh hotfix/revert-merge
để merge vào nhánh release
.
Khi Nào Nên Dùng Cách Nào?
- Revert từng commit: Phù hợp khi tính năng được đẩy lên với nhiều commit rời rạc hoặc anh em chỉ muốn revert một phần tính năng.
- Revert merge commit: Nhanh hơn nếu toàn bộ tính năng được merge qua một PR duy nhất, vì nó giúp revert toàn bộ PR một cách dễ dàng.
Kết Luận
Việc phải revert một tính năng trong Git là chuyện thường gặp khi làm việc theo nhóm. Tùy theo cách tính năng đó được merge vào nhánh release
, anh em có thể chọn cách revert từng commit hoặc revert toàn bộ PR một cách nhanh gọn. Mỗi phương pháp đều có ưu điểm riêng, nhưng quan trọng nhất là anh em cần giữ cho lịch sử commit của dự án sạch sẽ và không ảnh hưởng đến các phần khác đang hoạt động.
Hy vọng bài viết này giúp anh em hiểu rõ hơn về việc revert commit trong Git. Nếu có thắc mắc hoặc ý kiến gì, đừng ngại để lại bình luận nhé!
Gavin Nguyen!
Discussion (undefined)