Câu trả lời:
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).
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 revert
là 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.
git reset
và git checkout
có 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 --hard
và git 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>
và 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.
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 reset
nói với Git để di chuyển CHÍNH đến một cam kết khác. git checkout
mặ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.
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 B
phụ thuộc vào thay đổi trong A
, hoàn nguyên A
là 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 A
hoàn toàn
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.git reset --soft
chỉ đặt lại ĐẦU, git reset --hard
đặt lại đầu và thư mục làm việc của bạn.
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.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).
Đặ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
Nếu bạn đã phá vỡ cây nhưng không cam kết mã, bạn có thể sử dụng git reset
và nếu bạn chỉ muốn khôi phục một tệp, bạn có thể sử dụng git checkout
.
Nếu bạn phá vỡ cây và cam kết mã, bạn có thể sử dụng git revert HEAD
.
http://book.git-scm.com/4_und tiến_in_git_-_reset,_checkout_and_Vvert.html