Cách sử dụng Git Revert


107

Được git revertsử dụng như thế nào?

Điều này nghe có vẻ giống như một câu hỏi trùng lặp nhưng khi mọi người hỏi nó, câu trả lời thường là, sử dụng git resetnhư Hoàn nguyên về cam kết bởi hàm băm SHA trong Git?

Sau đó, khi ai đó hỏi cách sử dụng, git resetmọi người trả lời rằng bạn nên sử dụng git reverttheo Git - cách khôi phục

Trước khi bạn biết điều đó, 8 người khác nhau đã xuất hiện với những cách độc đáo của riêng họ để cứu cái mông của OP, tất cả đều nằm trong đầu bạn.

Vì vậy, chúng ta hãy thử và dán đoạn ngắn gọn và viết Hướng dẫn cho người giả git revert.

Một kịch bản: bạn đã hai lần cam kết làm chủ và điều tồi tệ của nó. Bạn đã thúc đẩy và những người khác có những thay đổi xấu của bạn.

Bạn muốn hoàn tác nó. Nó không phải là thứ mà bạn có thể tự hoàn tác trong mã, chẳng hạn như một trình hướng dẫn hoặc trình quản lý gói nào đó đã thay đổi rất nhiều thứ ở khắp nơi - bạn chỉ muốn đưa tất cả trở lại như cũ.

Đây là những gì kiểm soát nguồn là tất cả về. Tôi chắc rằng nó dễ dàng.

Được rồi, bạn sẽ sử dụng git revertnhưng làm thế nào?

Và sau khi chạy git revertbạn có phải làm gì khác sau đó không? Bạn có phải cam kết các thay đổi được hoàn nguyên được thực hiện hay hoàn nguyên trực tiếp cam kết với repo hay gì ??

Rõ ràng là bạn sẽ cần phải đẩy một lần nữa và có thể thông báo về quả bóng của bạn cho cả đội.

Câu trả lời:


119

git revert thực hiện một cam kết mới

git revert chỉ cần tạo một cam kết mới đối lập với một cam kết hiện có.

Nó để các tệp ở trạng thái giống như thể cam kết đã được hoàn nguyên chưa bao giờ tồn tại. Ví dụ, hãy xem xét ví dụ đơn giản sau:

$ cd /tmp/example
$ git init
Initialized empty Git repository in /tmp/example/.git/
$ echo "Initial text" > README.md
$ git add README.md
$ git commit -m "initial commit"
[master (root-commit) 3f7522e] initial commit
 1 file changed, 1 insertion(+)
 create mode 100644 README.md
$ echo "bad update" > README.md 
$ git commit -am "bad update"
[master a1b9870] bad update
 1 file changed, 1 insertion(+), 1 deletion(-)

Trong ví dụ này, lịch sử cam kết có hai lần cam kết và lần cuối cùng là lỗi. Sử dụng git revert:

$ git revert HEAD
[master 1db4eeb] Revert "bad update"
 1 file changed, 1 insertion(+), 1 deletion(-)

Sẽ có 3 cam kết trong nhật ký:

$ git log --oneline
1db4eeb Revert "bad update"
a1b9870 bad update
3f7522e initial commit

Vì vậy, có một lịch sử nhất quán về những gì đã xảy ra, nhưng các tệp vẫn như thể bản cập nhật xấu không bao giờ xảy ra:

cat README.md 
Initial text

Không quan trọng nơi trong lịch sử, cam kết được hoàn nguyên (trong ví dụ trên, cam kết cuối cùng được hoàn nguyên - bất kỳ cam kết nào cũng có thể được hoàn nguyên).

Câu hỏi kết thúc

bạn có phải làm gì khác sau khi?

Một git revertchỉ một cam kết, vì vậy ví dụ như đẩy để điều khiển từ xa để người dùng khác có thể kéo / lấy / trộn các thay đổi và bạn đã hoàn tất.

Bạn có phải cam kết hoàn nguyên các thay đổi được thực hiện hay hoàn nguyên trực tiếp cam kết với repo?

git revert một cam kết - không có bước bổ sung nào giả sử việc hoàn nguyên một cam kết duy nhất là những gì bạn muốn làm.

Rõ ràng là bạn sẽ cần phải thúc đẩy một lần nữa và có thể thông báo cho đội.

Thật vậy - nếu điều khiển từ xa ở trạng thái không ổn định - giao tiếp với phần còn lại của nhóm mà họ cần kéo để sửa lỗi (cam kết hoàn nguyên) sẽ là điều đúng đắn cần làm :).


Bằng cách xác nhận, cho cả câu lệnh đầu tiên ở đây và cho bất kỳ ai tự hỏi điều tương tự mà tôi chỉ thắc mắc về cách hoạt động của nó, bạn có thể hoàn nguyên một hoàn nguyên, nơi có một số cam kết mới kể từ khi hoàn nguyên mà bạn đang hoàn nguyên. Vì vậy, hoàn nguyên thực sự chỉ là một cam kết ngược lại với cam kết hoàn nguyên. Tất nhiên, bạn có thể có xung đột ... nhưng đó là một câu chuyện khác.
GG2

Tôi luôn nhận thấy tốt hơn để tránh cam kết với nó, chỉ để xem lại những thay đổi đầu tiên và tôi sử dụng, git revert -n <commitToRevet> hoặc git revert --no-commit <commitToRevet>
Eklavyaa

2
Tôi chỉ muốn nói rằng sau nhiều năm sử dụng stackoverflow, tôi nghĩ đây có thể là một trong những câu trả lời hay nhất mà tôi từng gặp. Ví dụ và giải thích tuyệt vời. Cảm ơn bạn.
user3344977

Tôi vào đây với hy vọng nhận được thêm thông tin, giống như TLDR của raw.githubusercontent.com/git/git/master/Documentation/howto/…
wviana

1
@wviana Nếu thông tin bạn tìm thấy không đủ, vui lòng viết câu trả lời. Lưu ý rằng tràn ngăn xếp không thể thay thế cho tài liệu chính thức (mà bạn dường như đang liên kết đến và bao gồm phạm vi rộng hơn nhiều so với câu hỏi này).
Ngày

35

Sử dụng git hoàn nguyên như vậy:

git revert <insert bad commit hash here>

git reverttạo một cam kết mới với các thay đổi được khôi phục. git resetxóa lịch sử git của bạn thay vì thực hiện một cam kết mới.

Các bước sau tương tự như bất kỳ cam kết nào khác.


Sự khác biệt giữa "hoàn nguyên một cam kết" và "hoàn nguyên thành một cam kết" đủ tinh tế mà tôi đã phải vật lộn với lệnh này trong nhiều năm. Lời giải thích của bạn đã giải quyết nó cho tôi ngay lập tức. Cảm ơn!
claviska

24

Lý do resetrevertcó xu hướng xuất hiện nhiều trong các cuộc trò chuyện giống nhau là do các hệ thống kiểm soát phiên bản khác nhau sử dụng chúng để có ý nghĩa khác nhau.

Đặc biệt, những người đã quen với SVN hoặc P4, những người muốn loại bỏ các thay đổi chưa cam kết đối với một tệp thường sẽ đạt được reverttrước khi được thông báo rằng họ thực sự muốn reset.

Tương tự, từ reverttương đương trong các VCS khác thường được gọi rollbackhoặc một cái gì đó tương tự - nhưng "rollback" cũng có thể có nghĩa là "Tôi muốn hủy hoàn toàn một số lần cam kết cuối cùng", điều này phù hợp resetnhưng không revert. Vì vậy, có rất nhiều sự nhầm lẫn khi mọi người biết họ muốn làm gì, nhưng không rõ họ nên sử dụng lệnh nào cho việc đó.

Đối với câu hỏi thực tế của bạn về hoàn nguyên ...

Được rồi, bạn sẽ sử dụng git revert nhưng làm thế nào?

git revert first-bad-commit..last-bad-commit

Và sau khi chạy git revert, bạn có phải làm gì khác sau đó không? Bạn có phải cam kết các thay đổi được hoàn nguyên được thực hiện hay hoàn nguyên trực tiếp cam kết với repo hay gì ??

Theo mặc định, git revertsẽ nhắc bạn về một thông báo cam kết và sau đó cam kết kết quả. Điều này có thể được ghi đè. Tôi trích dẫn trang người đàn ông :

--biên tập

Với tùy chọn này, git revert sẽ cho phép bạn chỉnh sửa thông báo cam kết trước khi hoàn nguyên. Đây là mặc định nếu bạn chạy lệnh từ một thiết bị đầu cuối.

- không cam kết

Thông thường, lệnh tự động tạo một số cam kết với thông báo nhật ký cam kết cho biết cam kết nào đã được hoàn nguyên. Cờ này áp dụng các thay đổi cần thiết để hoàn nguyên các cam kết đã đặt tên về cây làm việc và chỉ mục của bạn, nhưng không thực hiện các cam kết. Ngoài ra, khi tùy chọn này được sử dụng, chỉ mục của bạn không phải khớp với cam kết HEAD. Việc hoàn nguyên được thực hiện đối với trạng thái ban đầu của chỉ mục của bạn.

Điều này hữu ích khi hoàn nguyên nhiều hiệu ứng cam kết đến chỉ mục của bạn liên tiếp.

Đặc biệt, theo mặc định, nó tạo một cam kết mới cho mỗi cam kết mà bạn đang hoàn nguyên. Bạn có thể sử dụng revert --no-commitđể tạo các thay đổi hoàn nguyên tất cả chúng mà không cần cam kết các thay đổi đó như cam kết riêng lẻ, sau đó cam kết tùy ý.


git revert first-bad-commit..last-bad-commit: Tôi nghĩ điều này nên được git revert parent-of-first-bad-commit..last-bad-commit.
dùng1071847 20/09/19

9

Câu hỏi khá cũ nhưng hoàn nguyên vẫn khiến mọi người (như tôi) bối rối

Là một người mới bắt đầu, sau một số lần thử và sai (nhiều lỗi hơn so với thử nghiệm), tôi có một điểm quan trọng:

  • git revertyêu cầu id của cam kết mà bạn muốn xóa, lưu nó vào lịch sử của bạn

  • git resetyêu cầu cam kết bạn muốn giữ và do đó sẽ xóa mọi thứ sau đó khỏi lịch sử.

Nghĩa là, nếu bạn sử dụng revertvới id cam kết đầu tiên, bạn sẽ thấy mình vào một thư mục trống và một cam kết bổ sung trong lịch sử, trong khi với việc đặt lại thư mục của bạn sẽ được .. hoàn nguyên về cam kết ban đầu và lịch sử của bạn sẽ nhận được như thể (các) cam kết cuối cùng không bao giờ xảy ra.

Để rõ ràng hơn nữa, với một nhật ký như thế này:

# git log --oneline

cb76ee4 wrong
01b56c6 test
2e407ce first commit

Sử dụng git revert cb76ee4ý theo mặc định đưa tập tin của bạn trở lại 01b56c6 và sẽ bổ sung thêm cam kết lịch sử của bạn:

8d4406b Revert "wrong"
cb76ee4 wrong
01b56c6 test
2e407ce first commit

git reset 01b56c6 thay vào đó sẽ đưa các tệp của bạn trở lại 01b56c6 và sẽ xóa mọi cam kết khác sau đó khỏi lịch sử của bạn:

01b56c6 test
2e407ce first commit

Tôi biết đây là "cơ sở" nhưng nó khá khó hiểu đối với tôi, bằng cách chạy reverttrên id đầu tiên ('cam kết đầu tiên'), tôi đã hy vọng tìm thấy các tệp ban đầu của mình, phải mất một lúc để hiểu rằng nếu bạn cần lấy lại tệp của mình là 'cam kết đầu tiên', bạn cần sử dụng id tiếp theo.


Tôi đã quan sát như vậy. nó thực sự khó hiểu nhưng rất quan trọng cần biết. vừa rồi tôi phải giúp một đồng nghiệp và quên mất điều này. Đó là một chút xấu hổ.
ExOfDe

1

Tôi đã hoàn nguyên một số cam kết bằng cách chạy 'git revert commit id', chẳng hạn như:

git revert b2cb7c248d416409f8eb42b561cbff91b0601712

Sau đó, tôi được nhắc thực hiện việc hoàn nguyên (giống như bạn sẽ làm khi chạy 'git commit'). Chương trình đầu cuối mặc định của tôi là Vim nên tôi đã chạy:

:wq 

Cuối cùng tôi đã đẩy thay đổi vào kho lưu trữ với:

git push
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.