Command Palette

Search for a command to run...

[Git nâng cao] Git Reset hay Git Revert? Lựa chọn hoàn tác đúng cách

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 resetgit 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.

Git Reset hay Git Revert? Lựa chọn hoàn tác đúng cách

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 đô":

  1. 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ạn git commit -m "Commit gộp siêu gọn gàng".
  2. 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.
  3. 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!

⚠️ 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 hay develop. 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 độngDi chuyển con trỏ HEAD về quá khứ.Tạo một commit mới ở hiện tại.
Trường hợp dùngDọ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ánh feature của riêng tôi. Tôi chưa push đi đâu cả!"

    • Giải pháp: git reset. Đây là lúc reset 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.
  • 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ùng reset.
    • 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.
  • 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".

Kết luận: Cần làm chủ cả Git Reset và Git Revert

Việc lựa chọn giữa git resetgit 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!

Bài viết liên quan

[Git nâng cao] Git reflog: Phục hồi lịch sử commit và mọi thao tác trong Git

Git reflog là gì? Hướng dẫn chi tiết cách dùng lệnh git reflog để xem lại lịch sử các thao tác và khôi phục những thay đổi, đảm bảo bạn không bao giờ mất code nữa.

[Git nâng cao] Git cherry-pick là gì? Câu lệnh "thần kỳ" giúp chọn lọc commit

Git cherry-pick không đơn thuần chỉ là sao chép commit. Bài viết sẽ bật mí những thủ thuật giúp bạn sử dụng lệnh này hiệu quả, tránh các lỗi thường gặp và tối ưu hóa quy trình làm việc trên Git.

[Git nâng cao] Git Tag là gì? Cách dùng và cách ứng dụng trong thực tế

Bạn muốn đánh dấu các phiên bản quan trọng của dự án? Git Tag chính là công cụ bạn cần. Tìm hiểu cách sử dụng Git Tag để dễ dàng theo dõi và quản lý các bản release, từ đó nâng cao hiệu suất làm việc.

[Git nâng cao] Hướng dẫn Git Rebase: Hiểu rõ và sử dụng hiệu quả

Git Rebase dùng để sắp xếp lại, kết hợp và thay đổi các commit. Bài viết này sẽ giúp bạn phân biệt Git Rebase và Git Merge, đồng thời nắm vững cách dùng Git Rebase hiệu quả, an toàn.