Sự khác biệt giữa Git Revert, Checkout và Reset là gì?


273

Tôi đang cố gắng tìm hiểu làm thế nào để khôi phục hoặc các tập tin và các dự án rollback đến một trạng thái trước đó, và không hiểu sự khác biệt giữa git revert, checkoutreset. Tại sao có 3 lệnh khác nhau cho cùng một mục đích và khi nào thì ai đó nên chọn một lệnh khác?

Câu trả lời:


460

Ba lệnh này có mục đích hoàn toàn khác nhau. Chúng thậm chí không giống nhau từ xa.

git revert

Lệnh này tạo ra một cam kết mới hoàn tác các thay đổi từ một cam kết trước đó. Lệnh này thêm lịch sử mới vào dự án (nó không sửa đổi lịch sử hiện tại).

git checkout

Lệnh này kiểm tra nội dung từ kho lưu trữ và đặt nó vào cây công việc của bạn. Nó cũng có thể có các hiệu ứng khác, tùy thuộc vào cách lệnh được gọi. Chẳng hạn, nó cũng có thể thay đổi chi nhánh mà bạn hiện đang làm việc. Lệnh này không thực hiện bất kỳ thay đổi nào đối với lịch sử.

git reset

Lệnh này phức tạp hơn một chút. Nó thực sự làm một vài điều khác nhau tùy thuộc vào cách nó được gọi. Nó sửa đổi chỉ mục (cái gọi là "khu vực tổ chức"). Hoặc nó thay đổi mà cam kết một chi nhánh hiện đang chỉ vào. Lệnh này có thể thay đổi lịch sử hiện tại (bằng cách thay đổi cam kết mà một nhánh tham chiếu).

Sử dụng các lệnh này

Nếu một cam kết đã được thực hiện ở đâu đó trong lịch sử của dự án và sau đó bạn quyết định rằng cam kết đó là sai và không nên thực hiện, thì đó git revertlà công cụ cho công việc. Nó sẽ hoàn tác các thay đổi được đưa ra bởi cam kết xấu, ghi lại "hoàn tác" trong lịch sử.

Nếu bạn đã sửa đổi một tệp trong cây làm việc của mình, nhưng không cam kết thay đổi, thì bạn có thể sử dụng git checkoutđể kiểm tra bản sao mới từ kho lưu trữ của tệp.

Nếu bạn đã thực hiện một cam kết, nhưng chưa chia sẻ nó với bất kỳ ai khác và bạn quyết định rằng bạn không muốn nó, thì bạn có thể sử dụng git resetđể viết lại lịch sử để nó trông như thể bạn chưa bao giờ thực hiện cam kết đó.

Đây chỉ là một số tình huống sử dụng có thể. Có một số lệnh khác có thể hữu ích trong một số trường hợp và ba lệnh trên cũng có những cách sử dụng khác.


13
Vì vậy, ba lệnh có thể được sử dụng để UNDO một số công việc, có nghĩa là chúng không "hoàn toàn khác nhau". Cùng một khái niệm, bối cảnh khác nhau.
Bruno Santos

16
@BrunoSantos: Nến, ống dẫn, dao găm và dây thừng đều có thể được sử dụng để giết người, nhưng điều đó không có nghĩa là bất kỳ thứ gì trong số đó đều đặc biệt giống nhau.
Dan

12
@Dan Mounlding - Trên thực tế, có nhiều trường hợp git resetgit checkoutcó thể làm điều tương tự chính xác. Nói rằng chúng "thậm chí không giống nhau từ xa" không chỉ là một sự cường điệu quá mức: nó thậm chí không phải là sự thật từ xa. Hai lệnh này có thể làm rất nhiều thứ khác nhau, một số trong đó hoàn toàn trùng lặp. Ví dụ: git reset --hardgit checkout -- .sẽ làm chính xác điều tương tự. Và nói một cách logic, git reset --hard <path>git checkout <path>cũng nên làm điều tương tự chính xác - tuy nhiên git ngăn bạn làm điều đó. Nhầm lẫn hai lệnh này là RẤT dễ dàng.
DanGordon

5
@DanGordon Tôi nhận ra có lẽ chúng ta sẽ có một sự khác biệt về quan điểm ở đây. Tuy nhiên, tôi cảm thấy tôi nên cung cấp một số lời giải thích. Bạn không thể làm git reset --hard <path>như bạn có thể git checkout <path>chính xác bởi vì hai lệnh làm một cái gì đó hoàn toàn khác nhau. git resetnói với Git để di chuyển CHÍNH đến một cam kết khác. git checkoutmặt khác không yêu cầu Git làm bất cứ điều gì với HEAD cả. Nó để lại một mình và chỉ kiểm tra một tập tin. Vâng, bạn có thể chế tạo chúng theo cách mà chúng có hiệu ứng tương tự. Nhưng những gì họ thực sự làm là hoàn toàn khác nhau.
Dan

46

Giả sử bạn đã cam kết:

C
B
A

git revert B, sẽ tạo ra một cam kết hoàn tác các thay đổi trong B.

git revert A, sẽ tạo một cam kết hoàn tác các thay đổi trong A, nhưng sẽ không chạm vào các thay đổi trongB

Lưu ý rằng nếu thay đổi Bphụ thuộc vào thay đổi trong A, hoàn nguyên Alà không thể.

git reset --soft A, sẽ thay đổi lịch sử cam kết và kho lưu trữ; thư mục dàn dựng và làm việc sẽ vẫn ở trạng thái C.

git reset --mixed A, sẽ thay đổi lịch sử cam kết, kho lưu trữ và dàn dựng; thư mục làm việc sẽ vẫn ở trạng thái C.

git reset --hard A, sẽ thay đổi lịch sử cam kết, kho lưu trữ, thư mục dàn dựng và làm việc; bạn sẽ trở lại trạng thái Ahoàn toàn


1
Vì vậy, câu trả lời trực quan .. làm thế nào về thanh toán
MJ Studio

29
  • git revertđược sử dụng để hoàn tác một cam kết trước đó. Trong git, bạn không thể thay đổi hoặc xóa một cam kết trước đó. (Trên thực tế bạn có thể, nhưng nó có thể gây ra vấn đề.) Vì vậy, thay vì chỉnh sửa cam kết trước đó, Revert giới thiệu một cam kết mới đảo ngược một cam kết trước đó.
  • git reset được sử dụng để hoàn tác các thay đổi trong thư mục làm việc của bạn chưa được ghi nhận.
  • git checkoutđược sử dụng để sao chép một tệp từ một số cam kết khác vào cây làm việc hiện tại của bạn. Nó không tự động cam kết tập tin.

7
Tôi tin rằng bạn đã sai về "git reset". "git reset" đặt lại ĐẦU của bạn thành một trong những cam kết trước đó, nó không thiết lập lại thư mục làm việc của bạn. Thư mục làm việc được "thiết lập lại" bằng "git checkout [tên tệp]"
luigi7up

11
git reset --softchỉ đặt lại ĐẦU, git reset --hardđặt lại đầu và thư mục làm việc của bạn.
Ehryk

git reset --mixed (mặc định): không phổ biến + thay đổi
giai đoạn

21
  • git checkout sửa đổi cây làm việc của bạn,
  • git reset sửa đổi tham chiếu chi nhánh mà bạn đang hướng tới,
  • git revert thêm một cam kết hoàn tác thay đổi.

4
git reset không chỉ sửa đổi cam kết mà một nhánh trỏ tới , nó cũng được sử dụng để bỏ các tệp khỏi chỉ mục và có thể sửa đổi bản sao làm việc với git reset --mixed(mặc định).

git reset --soft: những thay đổi không phổ biến, những thay đổi được để lại theo giai đoạn (chỉ mục). git reset --mixed (mặc định): không phổ biến + thay đổi giai đoạn, thay đổi được để lại trong cây làm việc. git reset --hard: unommit + unstage + xóa các thay đổi, không còn gì cả.
NattyC

6

Đặt lại - Trên cấp độ cam kết, đặt lại là một cách để di chuyển đầu nhánh sang một cam kết khác. Điều này có thể được sử dụng để loại bỏ các cam kết từ chi nhánh hiện tại.

Hoàn nguyên - Hoàn nguyên cam kết bằng cách tạo một cam kết mới. Đây là một cách an toàn để hoàn tác các thay đổi, vì nó không có cơ hội viết lại lịch sử cam kết. Tương phản điều này với thiết lập lại git, điều này làm thay đổi lịch sử cam kết hiện có. Vì lý do này, git Revert nên được sử dụng để hoàn tác các thay đổi trên một nhánh công cộng và git reset nên được dành riêng cho các thay đổi hoàn tác trên một nhánh riêng.

Bạn có thể xem liên kết này - Đặt lại, Thanh toán và Hoàn nguyên


Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.