Quay trở lại một cam kết Git cũ trong một repo công khai


802

Làm thế nào tôi có thể quay trở lại một cam kết cụ thể trong git ?

Câu trả lời tốt nhất mà ai đó có thể cho tôi là sử dụng git revertX lần cho đến khi tôi đạt được cam kết mong muốn.

Vì vậy, hãy nói rằng tôi muốn quay trở lại một cam kết cũ 20 lần, tôi phải chạy nó 20 lần.

Có cách nào dễ dàng hơn để làm điều này?

Tôi không thể sử dụng thiết lập lại vì kho lưu trữ này là công khai.


1
git hoàn nguyên <commit> không hoạt động?
miku

8
Như đã nêu trong câu hỏi của tôi, điều này thực sự không giúp ích gì cho tôi nếu tôi muốn quay trở lại một cái gì đó 20 lần cam kết trước đây.
David

7
Câu hỏi này đã được trả lời khá tốt ở đây stackoverflow.com/questions/4114095/ từ
user7610

4
Không rõ ý của bạn là gì khi "quay lại". Điều đó có nghĩa là bạn muốn tạm thời chuyển bản sao làm việc của bạn sang một bản sửa đổi cụ thể? Hoặc bạn có muốn hoàn nguyên vĩnh viễn lịch sử của kho lưu trữ của bạn trở lại một phiên bản nhất định không?

1
Bạn nên chấp nhận một câu trả lời, và có thể bỏ phiếu cho bất kỳ câu trả lời nào khác mà bạn thích.
Nabil Kadimi

Câu trả lời:


1194

Thử cái này:

git checkout [revision] .

nơi [revision]được cam kết băm (ví dụ: 12345678901234567890123456789012345678ab).

Đừng quên .cuối cùng, rất quan trọng. Điều này sẽ áp dụng thay đổi cho toàn bộ cây. Bạn nên thực hiện lệnh này trong root dự án git. Nếu bạn đang ở trong bất kỳ thư mục con nào, thì lệnh này chỉ thay đổi các tệp trong thư mục hiện tại. Sau đó cam kết và bạn nên được tốt.

Bạn có thể hoàn tác điều này bằng cách

git reset --hard 

sẽ xóa tất cả các sửa đổi từ thư mục làm việc và khu vực tổ chức.


7
@AlexReisner Khoảng thời gian đó tại các điểm cuối tại thư mục bạn hiện đang ở, không nhất thiết phải là toàn bộ dự án git, đúng không? Nếu bạn muốn áp dụng các thay đổi cho toàn bộ dự án, thay vào đó bạn sẽ sử dụng ': /' như trong 'git add: /', nếu bạn hiện không có trong root dự án git?
MSpreij

10
lưu ý: nếu bạn đã thêm các tệp mới vào dự án của mình kể từ đó, điều này sẽ không xóa chúng. Vì vậy, khi bạn đi xây dựng (tùy thuộc vào nền tảng của bạn), bạn có thể vẫn gặp lỗi. Xóa các tập tin mới và bạn tốt để đi.
TheWestIsThe ...

6
@MSpreij Bạn nên thực thi lệnh này trong root dự án git. Nếu bạn đang ở trong bất kỳ thư mục con nào, thì lệnh này chỉ thay đổi các tệp trong thư mục hiện tại.
volatilevar

3
Thật tuyệt vời khi bạn có thể sao chép một dự án trong một thư mục khác và sử dụng git checkout [sửa đổi]. để quay lại bản sửa đổi cụ thể và sau đó so sánh nó với cùng một dự án trong thư mục khác. Tiết kiệm được nhiều thời gian.
Donato

4
Chết tiệt, tôi quên mất "." Tôi đã làm gì thiệt hại cho kho lưu trữ của tôi?

196

Để quay trở lại một cam kết cụ thể:

git reset --hard commit_sha

Để khôi phục 10 cam kết trở lại:

git reset --hard HEAD~10

Bạn có thể sử dụng "git Revert" như trong bài viết sau nếu bạn không muốn viết lại lịch sử

Làm cách nào để hoàn nguyên kho Git về một xác nhận trước đó?


4
chỉ khác nhau giữa phương pháp này và "kiểm tra git [sửa đổi]." là cái sau bảo tồn sửa đổi.
deeshank

53
Câu trả lời này là SAI vì OP đặc biệt tuyên bố "Tôi không thể sử dụng thiết lập lại vì repo này là công khai"
Yarin

4
Nếu repo là công khai, tôi nghĩ không có cách nào để khôi phục lại cam kết trên kho lưu trữ công cộng mà không sử dụng lực đẩy (git đẩy -f) vì nó sẽ ảnh hưởng đến những người đã thay đổi trước khi quay lại. Vì vậy, thiết lập lại có thể được sử dụng trong hộp cát cục bộ của một repo công cộng.
Naga Kiran

4
Thật tuyệt khi điều này tránh được một TRỤ SỞ! Chỉ cần những gì tôi đang tìm kiếm.
nhà sư mạng

1
Trong trường hợp của tôi, điều này đã hoạt động, sau đó sử dụng 'git pull' để nhanh chóng quay trở lại đầu sau khi bạn đã kiểm tra hồi quy, v.v.
Peter Quires 16/03/18

86

Chà, tôi đoán câu hỏi là, "bạn quay lại" nghĩa là gì? Nếu bạn không thể resetvì nó công khai và bạn muốn giữ nguyên lịch sử cam kết, bạn có nghĩa là bạn chỉ muốn bản sao làm việc của mình phản ánh một cam kết cụ thể? Sử dụng git checkoutvà băm cam kết.

Chỉnh sửa: Như đã được chỉ ra trong các nhận xét, sử dụng git checkoutmà không chỉ định một chi nhánh sẽ khiến bạn ở trạng thái "không có chi nhánh". Sử dụng git checkout <commit> -b <branchname>để thanh toán vào một chi nhánh hoặc git checkout <commit> .để thanh toán vào chi nhánh hiện tại.


Điều này không đưa bạn vào trạng thái kỳ lạ 'Hiện tại không ở bất kỳ chi nhánh nào'? Làm thế nào để bạn cam kết thay đổi để hoàn thành rollback?
Alex Reisner

Chà, tôi chỉ đề nghị sử dụng git checkout- anh ấy có thể tự do kiểm tra bất kỳ chi nhánh nào (hiện tại hay mới) mà anh ấy muốn. Tôi sẽ cập nhật câu trả lời của mình để nó không mơ hồ.
Ben

2
Tôi đã thử điều này nhưng tôi không nghĩ rằng đây là cách thích hợp để làm điều đó vì nó khiến các tập tin bị đình trệ. Điều này không xóa các tập tin không có trong cam kết cuối cùng đó.
David

3
Nếu bạn đang ở trong một thư mục làm việc và bạn đang ở trong chế độ chính, bạn cần git resetxóa các tệp đó, điều mà bạn nói rằng bạn không muốn làm. Hãy thử thực hiện nó thành một nhánh riêng biệt : git checkout <commit> -b <branchname>, bạn sẽ không có các tệp bị trì trệ trong nhánh đó .
Ben

2
Vấn đề với việc sử dụng checkoutlà nó sẽ không xóa các tệp đã được thêm vào trong một cam kết trước đó.

42

Các poster gốc nêu rõ:

Câu trả lời tốt nhất mà ai đó có thể cho tôi là sử dụng git revertX lần cho đến khi tôi đạt được cam kết mong muốn.

Vì vậy, hãy nói rằng tôi muốn quay trở lại một cam kết cũ 20 lần, tôi phải chạy nó 20 lần.

Có cách nào dễ dàng hơn để làm điều này?

Tôi không thể sử dụng thiết lập lại vì repo này là công khai.

Không cần thiết phải sử dụng git revertX lần. git revertcó thể chấp nhận một phạm vi cam kết làm đối số, vì vậy bạn chỉ cần sử dụng nó một lần để hoàn nguyên một phạm vi cam kết. Ví dụ: nếu bạn muốn hoàn nguyên 20 lần xác nhận cuối cùng:

git revert --no-edit HEAD~20..

Phạm vi cam kết HEAD~20..là viết tắt của từ HEAD~20..HEADvà có nghĩa là "bắt đầu từ cha mẹ thứ 20 của cam kết CHÍNH và hoàn nguyên tất cả các cam kết sau khi lên đến CHÍNH".

Điều đó sẽ hoàn nguyên 20 lần xác nhận cuối cùng, giả sử rằng không ai trong số đó là hợp nhất. Nếu có các xác nhận hợp nhất, thì bạn không thể hoàn nguyên tất cả chúng trong một lệnh, bạn sẽ cần hoàn nguyên chúng một cách riêng lẻ với

git revert -m 1 <merge-commit>

Cũng lưu ý rằng tôi đã thử nghiệm sử dụng một phạm vi với git revertviệc sử dụng git phiên bản 1.9.0. Nếu bạn đang sử dụng phiên bản cũ hơn của git, sử dụng phạm vi có git revertthể có hoặc không hoạt động.

Trong trường hợp này, git revertđược ưa thích hơn git checkout.

Lưu ý rằng không giống như câu trả lời được sử dụng nàygit checkout , git revert sẽ thực sự xóa bất kỳ tệp nào được thêm vào trong bất kỳ cam kết nào mà bạn hoàn nguyên , điều này làm cho cách này chính xác để hoàn nguyên một loạt các sửa đổi.

Tài liệu


Lưu ý : điều này tạo ra một cam kết mới với các thay đổi được hoàn nguyên. Hoàn hảo cho câu hỏi của OP. Nhưng hãy chắc chắn rằng đó là những gì bạn muốn. (Các ví dụ trong tài liệu git- Revert được liên kết ở trên là tuyệt vời.) Thay vào đó, nếu bạn muốn điều tra các cam kết trước đó (nghĩa là trước khi chọn cam kết hoàn nguyên), hãy sử dụng tùy chọn thanh toán được đề cập trong các câu trả lời khác thực hiện về các tập tin bị xóa.
SherylHohman

@SherylHohman Trở lại cam kết trước đó không tạo ra một cam kết mới. Tôi không thể tưởng tượng những gì bạn có ý nghĩa ở đây.

27

Bước 1: tìm nạp danh sách các xác nhận:

git log

Bạn sẽ nhận được danh sách như trong ví dụ này:

[Comp:Folder User$ git log
commit 54b11d42e12dc6e9f070a8b5095a4492216d5320
Author: author <author@gmail.com>
Date:   Fri Jul 8 23:42:22 2016 +0300

This is last commit message

commit fd6cb176297acca4dbc69d15d6b7f78a2463482f
Author: author <author@gmail.com>
Date:   Fri Jun 24 20:20:24 2016 +0300

This is previous commit message

commit ab0de062136da650ffc27cfb57febac8efb84b8d
Author: author <author@gmail.com>
Date:   Thu Jun 23 00:41:55 2016 +0300

This is previous previous commit message
...

Bước 2: sao chép hash hash cần thiết và dán nó để kiểm tra:

git checkout fd6cb176297acca4dbc69d15d6b7f78a2463482f

Đó là tất cả.


11
git read-tree -um @ $commit_to_revert_to

sẽ làm điều đó. Đó là "git checkout" nhưng không cập nhật CHÍNH.

Bạn có thể đạt được hiệu quả tương tự với

git checkout $commit_to_revert_to
git reset --soft @{1}

nếu bạn thích xâu chuỗi các lệnh tiện lợi với nhau.

Những thứ này để lại cho bạn với worktree và chỉ mục của bạn ở trạng thái mong muốn, bạn chỉ có thể git commithoàn thành.


Đây là cách tiếp cận đơn giản duy nhất hoạt động như một bùa mê! Tôi đã kiểm tra từ đầu, chạy lệnh này và nó đã xóa thành công các tệp mà chúng tôi đã giới thiệu và hoàn nguyên tất cả các thay đổi. Thông minh.
kamranicus 16/03/18

6

Muốn chế độ tách rời ĐẦU?

Nếu bạn muốn quay ngược thời gian X đến một cam kết nhất định với ĐẦU XÁC ĐỊNH (có nghĩa là bạn không thể làm hỏng bất cứ điều gì), thì bằng mọi cách, hãy sử dụng như sau:

(thay thế X bằng số lần xác nhận bạn muốn quay lại)

git checkout HEAD~X

IE quay trở lại một cam kết:

git checkout HEAD~1

1
Tôi sẽ xóa phần đó bằng ... khó tin ... Có vẻ như cá nhân, và cũng có người đã đề cập nó vào một bình luận ở trên, và trong @ken cũng trong câu trả lời của anh ấy.
meJustAndrew

@meJustAndrew Đó là, rất nhiều câu trả lời về SO mà chỉ khiến mọi người nhầm lẫn, nó khá khó chịu.
Karl Morrison

Thật là một câu trả lời đơn giản và thẳng về phía trước.
Ammad

2

Giả sử bạn làm việc trong một dự án và sau một ngày hoặc lâu hơn. Bạn nhận thấy một tính năng vẫn còn cho bạn lỗi. Nhưng bạn không biết những thay đổi bạn đã gây ra lỗi. Vì vậy, bạn phải đánh cá cam kết làm việc trước đó. Để trở lại một cam kết cụ thể:

git checkout 8a0fe5191b7dfc6a81833bfb61220d7204e6b0a9 .

Ok, để cam kết làm việc cho bạn. Không còn lỗi nữa. Bạn xác định chính xác vấn đề. Bây giờ bạn có thể quay lại cam kết mới nhất:

git checkout 792d9294f652d753514dc2033a04d742decb82a5 .

Và kiểm tra một tệp cụ thể trước khi nó gây ra lỗi (trong trường hợp của tôi, tôi sử dụng ví dụ Gemfile.lock):

git checkout 8a0fe5191b7dfc6a81833bfb61220d7204e6b0a9 -- /projects/myproject/Gemfile.lock

Và đây là một cách để xử lý các lỗi bạn đã tạo trong các lần xác nhận mà không nhận ra các lỗi cho đến sau này.


2

Bạn có thể tìm thấy id xác nhận liên quan đến từng cam kết trong phần cam kết của GitHub / BitBucket / Gitlab. Rất đơn giản, giả sử id cam kết của bạn là 5889575 thì nếu bạn muốn quay lại phần này trong mã của mình thì bạn chỉ cần gõ

git checkout 5889575 .

Điều này sẽ đưa bạn đến thời điểm đó trong mã của bạn.


1

Tôi không chắc chắn điều gì đã thay đổi, nhưng tôi không thể kiểm tra một cam kết cụ thể mà không có tùy chọn --detach. Lệnh đầy đủ làm việc cho tôi là: git checkout --detach [commit hash]

Để trở về từ trạng thái tách ra, tôi phải kiểm tra chi nhánh địa phương của mình: git checkout master


Kiểm tra mastergiải quyết vấn đề còn lại tách ra, trong khi làm git reset --hardhoặc git checkout -- .đã làm nhưng vẫn tách ra
DarkCygnus

0

Dưới đây là một ví dụ để làm điều đó

    cd /yourprojects/project-acme 


    git checkout efc11170c78 .
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.