Chuyển đến nội dung chính

Git Revert Commit Cuối: Cách Hoàn tác Thay đổi An toàn trong Git

Tìm hiểu cách dùng git revert để hoàn tác commit Git gần nhất mà không viết lại lịch sử. Hiểu tác động của nó, so sánh với git reset và xử lý các trường hợp biên thực tế.
· 8 phút đọc

Khám phá cùng AI

Trong phát triển phần mềm, sai sót là điều khó tránh khỏi, nhưng cách bạn xử lý chúng mới là điều quan trọng, đặc biệt khi làm việc theo nhóm.

Khi làm việc với Git trong một kho dùng chung, bạn không chỉ muốn hoàn tác một commit lỗi; bạn còn muốn làm điều đó một cách an toàn. Đây là lý do tôi viết, từ kinh nghiệm của mình, một bài về git revert.

Thay vì xóa lịch sử như git reset, git revert tạo một commit mới để hoàn tác những thay đổi của commit trước đó. Cách tiếp cận này giữ nguyên lịch sử commit của bạn.

Nếu bạn còn mới với các khái niệm này, hãy tham gia lộ trình kỹ năng Git Fundamentals của chúng tôi để tìm hiểu mọi thứ về kho và kiểm soát phiên bản.

Git Revert là gì và hoạt động như thế nào?

Hãy coi git revert như cách Git nói: "Hoàn tác điều đó một cách an toàn." Khi có thứ gì đó lọt vào một commit — có thể là một lỗi, một lỗi đánh máy, hoặc một thay đổi vội vàng — bạn có thể muốn xóa nó. Nhưng trong một repo dùng chung, xóa lịch sử có thể gây rắc rối còn hơn cả lỗi ban đầu. Đó là lý do git revert tồn tại. Thay vì xóa commit, nó thêm một commit mới để triệt tiêu các thay đổi.

Vậy git revert làm gì?

  • Nó thêm một commit mới: Như tôi đã đề cập, thay vì xóa bất cứ thứ gì, git revert tạo một commit mới để hoàn tác những thay đổi cụ thể từ commit bạn đang revert. Điều này giữ lịch sử dự án của bạn nhất quán.

  • Nó áp dụng thay đổi ngay lập tức: Và như tôi chưa nói, ngay khi bạn chạy lệnh git revert, các thay đổi đã được hoàn tác sẽ xuất hiện trong thư mục làm việc của bạn. Bạn sẽ thấy bản sửa có hiệu lực ngay.

  • Nó không can thiệp vào staging (trừ khi có xung đột): Một điều nữa cần biết: Git xử lý revert nội bộ. Nếu mọi việc suôn sẻ, bạn không cần phải stage tệp thủ công. Tuy nhiên, nếu Git không thể tự đảo ngược điều gì đó (chẳng hạn trong các merge phức tạp), nó sẽ yêu cầu bạn can thiệp và hỗ trợ.

Điều gì xảy ra sau khi revert một commit

Vậy là bạn đã chạy git revert. Chính xác thì điều gì vừa xảy ra? Thay vì xóa bất cứ thứ gì, Git tạo một commit mới đảo ngược các thay đổi từ commit bạn nhắm tới. Commit mới này được thêm lên trên lịch sử hiện có của bạn, nghĩa là commit gốc vẫn còn nguyên và hiển thị đầy đủ. Không có gì bị viết lại hay bị xóa; thay vào đó, Git thêm một lớp hiệu quả là nói: "Hoàn tác điều đó." Đồng thời, các thay đổi tệp từ việc đảo ngược đó được áp dụng ngay vào thư mục làm việc của bạn. Bạn sẽ thấy bản sửa có hiệu lực ngay, giống như mọi commit khác.

Toàn bộ quy trình này khiến git revert trở thành cách an toàn nhất để sửa lỗi đã được đẩy lên nhánh dùng chung. Mọi người trong nhóm đều có thể thấy những gì đã thay đổi, những gì đã bị revert và lý do, mà không gây nhầm lẫn hay gián đoạn công việc đang diễn ra.

So sánh git revert với git reset

Mặc dù cả git revert và git reset đều có thể dùng để hoàn tác commit, chúng hoạt động theo những cách khác nhau căn bản. git reset phù hợp cho các chỉnh sửa cục bộ, riêng tư. Nó cho phép bạn dọn dẹp những commit lộn xộn và đặt lại thư mục làm việc đúng như bạn muốn. Nhưng có một điểm cần lưu ý: nếu bạn đã đẩy công việc của mình rồi mới dùng git reset, bạn có thể làm hỏng công việc của đồng đội bằng cách thay đổi lịch sử commit dùng chung.

Ngược lại, git revert được thiết kế đặc biệt cho các nhánh dùng chung hoặc công khai. Thay vì xóa bỏ, nó tạo một commit mới để triệt tiêu thay đổi của commit trước đó. Điều này khiến nó an toàn hơn trong các dự án cộng tác.

Dưới đây là so sánh song song để giúp làm rõ hơn:

Tính năng

git revert

git reset

Hành động

Thêm một commit mới đảo ngược commit trước đó

Di chuyển con trỏ nhánh và tùy chọn sửa đổi tệp

Lịch sử Commit

Được giữ nguyên, không xóa gì

Các commit bị viết lại có thể bị mất

Tốt nhất dùng cho

Hoàn tác thay đổi trên nhánh công khai/dùng chung

Dọn dẹp các commit cục bộ trước khi đẩy

Tác động đến người khác

An toàn, không gây gián đoạn cho cộng tác viên

Rủi ro, có thể gây xung đột nếu lịch sử được chia sẻ

Thư mục làm việc

Thay đổi được áp dụng ngay

Có thể đặt lại trạng thái tệp (--soft, --mixed, --hard)

Kịch bản lý tưởng

Đảo ngược một commit lỗi đã được đẩy

Viết lại lịch sử commit trong nhánh tính năng cục bộ

Revert nhiều commit

Đôi khi không chỉ một commit lỗi, bạn có thể cần hoàn tác cả một loạt. May mắn là Git cho phép bạn revert nhiều commit trong một lệnh bằng cách dùng một phạm vi commit.

Cú pháp như sau:

git revert OLDEST_HASH^..NEWEST_HASH

Điều này bảo Git bắt đầu từ ngay trước commit cũ nhất (đó là ý nghĩa của ký hiệu ^) và revert từng commit cho đến và bao gồm cả commit mới nhất. Ví dụ:

git revert a1b2c3d^..d4e5f6g

Lệnh này sẽ tạo các commit revert riêng biệt cho từng commit gốc trong phạm vi đó.

Lưu ý, revert nhiều commit cùng lúc thường có thể kích hoạt xung đột hợp nhất, đặc biệt nếu các commit đó chỉnh sửa cùng tệp hoặc cùng dòng. Git sẽ cố gắng đảo ngược từng commit theo thứ tự, nhưng có thể cần bạn hỗ trợ để xử lý các thay đổi chồng lấn.

Bạn cũng có thể đọc thêm về cách Git xử lý thao tác revert, bao gồm các trường hợp khó hơn như commit hợp nhất trong Git Revert Merge Commit: A Guide With Examples.

Xử lý xung đột hợp nhất khi revert

Revert nghe có vẻ đơn giản cho đến khi Git ném cho bạn một quả bóng cong - một xung đột hợp nhất. Những xung đột này thường xuất hiện khi:

  • Bạn đang revert một commit đã thay đổi cùng dòng với các commit gần đây khác.
  • Bạn đang revert một commit hợp nhất, hoặc một nhóm commit có thay đổi chồng lấn.

Git sẽ cố gắng đảo ngược các thay đổi một cách sạch sẽ, nhưng nếu có mơ hồ, nó sẽ tạm dừng và yêu cầu bạn trợ giúp.

Cách xử lý như sau:

git revert HEAD

Và để kiểm tra tệp nào đang xung đột, dùng:

git status

Để tự xử lý xung đột trong trình soạn thảo mã, hãy tìm các ký hiệu <<<<<<<, =======, và >>>>>>>.

Ở đây, tôi đánh dấu chúng là đã được giải quyết:

git add <resolved-file>

Bây giờ, tôi tiếp tục quá trình revert:

git revert-- continue

Nếu bạn đổi ý và muốn hủy bỏ hoàn toàn việc revert:

git revert --abort

Quy trình này cho bạn toàn quyền kiểm soát. Bạn có thể quyết định tiếp tục revert hoặc rút lui hoàn toàn.

Nếu bạn muốn hiểu cách Git theo dõi nhật ký tham chiếu trong các thao tác như thế này, hãy xem Git Reflog: Understanding and Using Reference Logs để nhận mẹo khắc phục lịch sử rối.

Trường hợp đặc biệt: Revert các merge commit

Revert một commit thông thường thì đơn giản, nhưng commit hợp nhất lại là câu chuyện khác. Bởi vì một merge commit có hai hoặc nhiều cha, và Git cần biết đường nào (hay "mainline") sẽ được coi là cơ sở.

Để revert một merge commit, bạn cần dùng cờ -m một cách tường minh.

git revert -m 1 <merge-commit-hash>

Cờ -m làm gì:

  • -m là viết tắt của mainline, báo cho Git biết commit cha nào sẽ được giữ.

  • 1 thường chỉ cha thứ nhất, thường là nhánh bạn đang ở khi thực hiện merge.

  • 2 chỉ cha thứ hai, thường là nhánh được merge vào.

Khi nào dùng 1 hoặc 2?

  • Dùng -m 1 nếu bạn muốn hoàn tác tác động của các thay đổi được merge vào nhưng giữ lại phần việc từ nhánh chính của bạn.

  • Dùng -m 2 nếu bạn muốn loại bỏ các thay đổi của mainline nhưng giữ lại nội dung của nhánh tính năng hoặc nhánh được merge. Trường hợp này hiếm. Revert một merge commit dễ phát sinh xung đột và thường dẫn đến tình huống phức tạp, đặc biệt nếu có các commit tiếp theo phụ thuộc vào nó. Nếu bạn chưa chắc, hãy thử revert trên một nhánh thử nghiệm trước.

Thực hành tốt khi dùng git revert

Để tận dụng tối đa git revert và tránh những sai lầm thường gặp, hãy ghi nhớ các thực hành tốt sau:

  • Xác minh hash commit trước khi revert: Luôn kiểm tra lịch sử commit bằng git log hoặc git log-- oneline để đảm bảo bạn đang nhắm đúng thay đổi. Bạn có thể ôn lại các lệnh này trong Foundations of Git hoặc giữ những điều cốt lõi trong tầm tay với Git Cheat Sheet của chúng tôi.

  • Tùy chỉnh thông điệp commit: Đừng chấp nhận thông điệp mặc định “Revert” của Git. Hãy thêm ngữ cảnh — như lý do bạn revert commit — để giúp cộng tác viên (và chính bạn trong tương lai) hiểu thay đổi.

  • Trao đổi khi revert trên các nhánh dùng chung: Nếu bạn đang revert thay đổi trên nhánh công khai, chẳng hạn main hoặc develop, hãy thông báo cho nhóm trước. Revert ảnh hưởng đến tất cả mọi người, và tốt nhất là nên phối hợp. Tìm hiểu thêm về quy trình làm việc hợp tác trong các khóa GitHub Concepts và Intermediate GitHub Concepts của chúng tôi.

  • Tránh revert một revert trừ khi bạn chắc chắn: Revert một lần revert trước đó có thể đưa trở lại các thay đổi không mong muốn hoặc gây xung đột. Nếu cần áp dụng lại một thay đổi, hãy cân nhắc dùng git cherry-pick thay thế.

  • Dùng reflog để khôi phục nếu mọi thứ trật hướng: Lỡ mắc lỗi giữa chừng khi revert? Hãy dùng git reflog để xem các thao tác gần đây và khôi phục trạng thái đã mất.

Kết luận

Nếu bạn đang cộng tác trong môi trường chuyên nghiệp, dùng git revert cho commit cuối bằng git revert HEAD giúp duy trì tính minh bạch đồng thời giảm nguy cơ mất dữ liệu do vô ý. Dù bạn đang dọn lỗi hay quay lại một bug, revert sẽ giữ repo của bạn ổn định và dễ hiểu cho mọi người liên quan.

Oluseye Jeremiah

Tác giả

Oluseye Jeremiah

Nhà viết nội dung về công nghệ, chuyên về AI, ML và khoa học dữ liệu, giúp làm rõ và phổ biến những ý tưởng phức tạp.

Chủ đề

Liên quan