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

VnnTools

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

[Git cơ bản] Git Branch là gì? Hiểu rõ và làm chủ phân nhánh trong Git

Branch là một tính năng quan trọng giúp chia nhỏ dự án trong Git. Đọc bài viết để hiểu rõ về Git Branch, cách tạo, xóa, và chuyển đổi giữa các nhánh một cách dễ dàng.

[Git cơ bản] Git Repository: Nền tảng quan trọng cho quản lý mã nguồn

Git Repository là nền tảng cốt lõi của Git. Khám phá cách Git Repository giúp bạn quản lý, theo dõi lịch sử thay đổi và hợp tác hiệu quả trong dự án lập trình.

[Git cơ bản] Git là gì? Khám phá vai trò của Git trong lập trình

Git là hệ thống quản lý phiên bản cực kỳ phổ biến. Bài viết này sẽ giải thích Git là gì, tại sao mọi developer đều cần biết Git và các bước để bắt đầu sử dụng.