Trong thế giới lập trình, Git như là một "cỗ máy thời gian" không thể thiếu. Nó cho phép chúng ta quay trở lại bất kỳ thời điểm nào trong lịch sử dự án. Nhưng khi bạn lỡ tay "commit" một lỗi ngớ ngẩn, một file nhạy cảm, hay đơn giản là muốn dọn dẹp lại lịch sử commit, bạn sẽ dùng chức năng nào của cỗ máy?
Hai lựa chọn mạnh mẽ nhất trong Git chính là git reset
và git revert
. Cả hai đều có khả năng "hoàn tác" các thay đổi, nhưng chúng thực hiện điều đó theo hai triết lý hoàn toàn khác nhau. Hiểu sai sự khác biệt này có thể dẫn đến việc mất code hoặc phá vỡ lịch sử của cả đội.
Bài viết này sẽ giúp bạn làm chủ cả hai, biết chính xác khi nào nên dùng git reset
và khi nào nên dùng git revert
.
Viết lại lịch sử với Git Reset 📜
Hãy tưởng tượng lịch sử commit của bạn là một cuốn biên niên sử. git reset
giống như một nhà sử học có quyền năng xé bỏ những trang cuối cùng và viết lại chúng. Nó không tạo ra một chương mới để sửa lỗi; nó xóa sổ hoàn toàn những gì đã được viết.
git reset
hoạt động bằng cách di chuyển con trỏ HEAD
(và tùy chọn cả chỉ mục Staging Area và Working Directory) đến một commit cũ hơn. Điều này có nghĩa là những commit sau điểm đó sẽ bị "mồ côi" và cuối cùng sẽ bị Git dọn dẹp vĩnh viễn.
Ba chế độ của Git Reset
git reset
có ba chế độ chính, từ nhẹ nhàng đến "nặng đô":
-
git reset --soft <commit>
: Nhẹ nhàng nhất 🟢- Hành động: Chỉ di chuyển con trỏ
HEAD
vềcommit
được chỉ định. - Staging Area & Working Directory: Hoàn toàn không thay đổi. Tất cả các thay đổi từ những commit đã bị "reset" sẽ được giữ lại trong Staging Area (sẵn sàng để được commit lại).
- Ví dụ: Bạn vừa commit 5 file riêng lẻ nhưng giờ muốn gộp chúng thành một commit duy nhất cho gọn. Bạn có thể
git reset --soft HEAD~5
, lúc này 5 commit đó biến mất nhưng toàn bộ thay đổi của chúng vẫn còn nguyên trong Staging Area, chờ bạngit commit -m "Commit gộp siêu gọn gàng"
.
- Hành động: Chỉ di chuyển con trỏ
-
git reset --mixed <commit>
(Đây là chế độ mặc định)- Hành động: Di chuyển
HEAD
và dọn dẹp Staging Area. - Staging Area: Các thay đổi sẽ bị xóa khỏi Staging Area.
- Working Directory: Không thay đổi. Các file của bạn vẫn còn nguyên, nhưng ở trạng thái "chưa được theo dõi" (unstaged). Bạn cần
git add
lại nếu muốn commit. - Ví dụ: Bạn vừa commit nhầm một file, bạn muốn hoàn tác commit đó và xem xét lại file trước khi
add
và commit lại.
- Hành động: Di chuyển
-
git reset --hard <commit>
: Nặng nề nhất 🔥- Hành động: Di chuyển
HEAD
, dọn dẹp Staging Area và xóa sạch mọi thay đổi trong Working Directory. - Staging Area & Working Directory: Cả hai đều được đặt lại về trạng thái chính xác của
commit
mà bạn reset tới. Mọi thay đổi chưa được commit sẽ biến mất vĩnh viễn. - Ví dụ: Bạn nhận ra toàn bộ những gì mình làm trong 3 commit gần nhất là sai lầm và muốn vứt bỏ hoàn toàn, không lưu luyến. Hãy dùng lệnh này một cách CỰC KỲ cẩn trọng!
- Hành động: Di chuyển
⚠️ Cảnh báo: KHÔNG BAO GIỜ sử dụng
git reset
(đặc biệt là--hard
) trên các commit đã được đẩy (push) lên một nhánh chung (public/shared branch) nhưmain
haydevelop
. Việc viết lại lịch sử mà đồng đội của bạn đã dựa vào sẽ gây ra xung đột và sự hỗn loạn tột độ.
Viết thêm phụ lục với Git Revert ✍️
Nếu git reset
là kẻ viết lại lịch sử, thì git revert
là một nhà sử học minh bạch và có trách nhiệm. Thay vì xé bỏ những trang sai, git revert
sẽ viết thêm một trang mới ở cuối, nói rằng: "Trang X đã có sai sót, và đây là nội dung đính chính."
git revert
hoạt động bằng cách xem xét một commit cũ, tìm ra những thay đổi trong commit đó, và tạo ra một commit mới chứa những thay đổi đối nghịch để vô hiệu hóa commit cũ.
Tại sao Git Revert lại an toàn?
- Không thay đổi lịch sử:
git revert
không xóa hay thay đổi bất kỳ commit nào đã tồn tại. Nó chỉ thêm vào lịch sử. Điều này giữ cho lịch sử dự án liền mạch, rõ ràng và dễ theo dõi. - An toàn cho hợp tác (Collaboration-safe): Vì lịch sử không bị viết lại, nó hoàn toàn an toàn để sử dụng trên các nhánh chung. Đồng đội của bạn chỉ cần
git pull
để nhận commit hoàn tác mới, mà không gặp bất kỳ xung đột lịch sử nào.
Cách hoạt động của Git Revert
Để hoàn tác một commit, bạn chỉ cần chạy:
git revert <mã-commit-cần-hoàn-tác>
Git sẽ tự động tạo một commit mới đảo ngược lại các thay đổi. Một trình soạn thảo văn bản sẽ hiện ra để bạn viết commit message cho hành động hoàn tác này.
🤝 Trường hợp sử dụng lý tưởng: Bạn phát hiện ra một bug được gây ra bởi một commit đã được đẩy lên nhánh
main
cách đây vài ngày. Cách xử lý an toàn và chuyên nghiệp nhất làgit revert
commit đó. Mọi người sẽ thấy rõ ràng rằng một commit đã được hoàn tác và lý do tại sao.
Bảng so sánh nhanh: Git Reset vs. Git Revert
Tiêu Chí | git reset (Xóa sổ và viết lại) | git revert (Tạo commit đảo ngược) |
---|---|---|
Lịch sử commit | 📜 Thay đổi lịch sử. Các commit cũ bị xóa. | ✍️ Bảo toàn lịch sử. Tạo ra commit mới. |
Mức độ an toàn | ⚠️ Nguy hiểm trên nhánh chung. An toàn trên nhánh cá nhân. | ✅ An toàn cho mọi loại nhánh, đặc biệt là nhánh chung. |
Tác động | Di chuyển con trỏ HEAD về quá khứ. | Tạo một commit mới ở hiện tại. |
Trường hợp dùng | Dọn dẹp lịch sử cục bộ, xóa commit sai trên nhánh cá nhân (chưa push). | Hoàn tác các thay đổi trên nhánh chung, minh bạch hóa việc sửa lỗi. |
Tình huống thực tế: Lựa chọn gì bây giờ? 💡
-
Tình huống 1: "Tôi vừa commit file
.env
chứa mật khẩu vào nhánhfeature
của riêng tôi. Tôi chưa push đi đâu cả!"- Giải pháp:
git reset
. Đây là lúcreset
tỏa sáng. git reset --hard HEAD~1
để xóa sổ commit sai lầm đó và cả file trong Working Directory. An toàn, nhanh, gọn.
- Giải pháp:
-
Tình huống 2: "Tính năng tôi vừa deploy lên môi trường Staging (từ nhánh
develop
) gây ra lỗi nghiêm trọng. Commit đó đã được push và nhiều người khác đã pull về."- Giải pháp:
git revert
. Tuyệt đối không dùngreset
. git revert <mã-commit-gây-lỗi>
và push commit hoàn tác này lên. Hệ thống sẽ được phục hồi, và lịch sử vẫn rõ ràng.
- Giải pháp:
-
Tình huống 3: "Tôi đã thực hiện 5 commit nhỏ nhặt, vụn vặt trên nhánh cá nhân. Tôi muốn gộp chúng thành 1 commit duy nhất trước khi tạo Pull Request."
- Giải pháp:
git reset --soft
. git reset --soft HEAD~5
rồi sau đógit commit -m "Một commit lớn đầy đủ tính năng"
.
- Giải pháp:
Kết luận: Cần làm chủ cả Git Reset và Git Revert
Việc lựa chọn giữa git reset
và git revert
phụ thuộc hoàn toàn vào bối cảnh: bạn đang làm việc trên lịch sử cá nhân hay lịch sử chung?
git reset
là công cụ mạnh mẽ để dọn dẹp và sửa chữa trên nhánh cá nhân của bạn. Hãy coi nó như một cục tẩy cá nhân.git revert
là công cụ an toàn và chuyên nghiệp để sửa lỗi trên nhánh mà bạn chia sẻ với người khác. Hãy coi nó như một bút toán đính chính công khai.
Nắm vững cả hai không chỉ giúp bạn tránh được những thảm họa Git, mà còn nâng tầm bạn thành một lập trình viên có khả năng quản lý phiên bản một cách chuyên nghiệp và có trách nhiệm. Chúc bạn có những chuyến du hành thời gian thành công trong thế giới Git!