Làm cách nào tôi có thể đặt lại hoặc hoàn nguyên tệp thành một bản sửa đổi cụ thể?


4517

Tôi đã thực hiện một số thay đổi đối với một tệp đã được cam kết một vài lần như là một phần của một nhóm các tệp, nhưng bây giờ muốn đặt lại / hoàn nguyên các thay đổi trên đó trở lại phiên bản trước.

Tôi đã thực hiện git logcùng với git diffviệc tìm bản sửa đổi mà tôi cần, nhưng tôi không biết làm thế nào để đưa tập tin trở lại trạng thái cũ trong quá khứ.


11
Sau khi hoàn nguyên, đừng quên --cachedkhi kiểm tra git diff. liên kết
Geoffrey Hale

5
Tôi tìm thấy câu hỏi của bạn khi tôi googled của tôi. Nhưng sau khi tôi đọc giải pháp, tôi đã kiểm tra nhật ký của mình và phát hiện ra rằng tôi đã thực hiện thay đổi của mình như một cam kết độc lập, vì vậy tôi đã hoàn trả lại cam kết đó và mọi thứ khác vẫn như tôi muốn. Không phải là một giải pháp, đôi khi chỉ là một cách khác để làm điều đó.
sudo97

Câu trả lời:


6136

Giả sử hàm băm của cam kết bạn muốn là c5f567:

git checkout c5f567 -- file1/to/restore file2/to/restore

Các git checkout trang người đàn ông mang lại cho biết thêm thông tin.

Nếu bạn muốn hoàn nguyên về cam kết trước đó c5f567, hãy thêm vào ~1(trong đó 1 là số lần xác nhận bạn muốn quay lại, đó có thể là bất cứ điều gì):

git checkout c5f567~1 -- file1/to/restore file2/to/restore

Một lưu ý phụ, tôi luôn cảm thấy khó chịu với lệnh này vì nó được sử dụng cho cả những thứ thông thường (thay đổi giữa các nhánh) và những thứ khác thường, phá hoại (loại bỏ những thay đổi trong thư mục làm việc).


12
@shadowhand: Có cách nào để đảo ngược điều đó, vì vậy đó là phiên bản ngay sau đó?
aliteralmind

16
@aliteralmind: Không, không may, ký hiệu phím tắt lịch sử Git chỉ đi ngược lại trong lịch sử.
Greg Hewgill

46
Nếu bạn sẽ sử dụng tên chi nhánh cho abcde (ví dụ develop) bạn sẽ muốn git checkout develop -- file/to/restore(lưu ý dấu gạch ngang kép)
Ohad Schneider

8
@aliteralmind: Trên thực tế, vâng, có một cách để làm điều đó: "git log --reverse -1 --ancestry-path yourgitrev..master" và sau đó sử dụng các tùy chọn thích hợp để chỉ lấy git rev. --ancestry-path sẽ "vẽ một đường" giữa hai lần xác nhận và -1 sẽ chỉ cho bạn một phiên bản và --reverse sẽ đảm bảo mục nhập đầu tiên được phát ra là mục cũ nhất.
Chris Cogdon

6
Cá nhân tôi thấy ĐẦU ^ dễ gõ hơn
TRƯỚC

606

Bạn có thể nhanh chóng xem lại các thay đổi được thực hiện đối với tệp bằng lệnh diff:

git diff <commit hash> <filename>

Sau đó, để hoàn nguyên một tệp cụ thể cho cam kết đó, hãy sử dụng lệnh đặt lại:

git reset <commit hash> <filename>

Bạn có thể cần phải sử dụng --hardtùy chọn nếu bạn có sửa đổi cục bộ.

Một quy trình công việc tốt để quản lý các điểm mốc là sử dụng các thẻ để đánh dấu sạch các điểm trong dòng thời gian của bạn. Tôi hoàn toàn không thể hiểu câu cuối cùng của bạn nhưng điều bạn có thể muốn là phân nhánh một nhánh từ thời điểm trước đó. Để làm điều này, sử dụng lệnh kiểm tra tiện dụng:

git checkout <commit hash>
git checkout -b <new branch name>

Sau đó, bạn có thể khởi động lại theo dòng chính của mình khi bạn sẵn sàng hợp nhất những thay đổi đó:

git checkout <my branch>
git rebase master
git checkout master
git merge <my branch>

7
Lệnh 'git checkout <commit hash>' đã đưa tôi trở lại phiên bản cũ hơn của dự án chính xác mà tôi đang tìm kiếm Cảm ơn Chris.
vidur trừngj

48
Để hoàn nguyên các tập tin git checkout <commit hash> <filename>làm việc tốt hơn cho tôi hơngit reset
Motti Strom

3
Tôi muốn có một phiên bản đầu tiên của một tệp vì tôi đã ghi đè lên 150 dòng với một bản sao / dán bị chọn sai. git checkout <commit hash> <filename>đã làm cho tôi. Đây không phải là câu trả lời được chấp nhận, IMHO. git resetđã không.
harperville

24
không thể sử dụng git resetđể đặt lại một tập tin, bạn sẽ gặp lỗifatal: Cannot do hard reset with paths
slier 23/12/14

13
Những gì slier nói: bạn không thể git reset --hard <commit hash> <filename>. Điều này sẽ có lỗi với fatal: Cannot do hard reset with paths.những gì Motti Strom đã nói: sử dụnggit checkout <commit hash> <filename>
Hawkeye Parker

366

Bạn có thể sử dụng bất kỳ tham chiếu nào đến cam kết git, bao gồm SHA-1 nếu thuận tiện nhất. Vấn đề là lệnh này trông như thế này:

git checkout [commit-ref] -- [filename]


22
Sự khác biệt giữa câu trả lời này có gì và câu trả lời --nào không?
2rs2ts

80
Trong git, một '-' trước danh sách tệp cho git biết rằng tất cả các đối số tiếp theo nên được hiểu là tên tệp, không phải là tên nhánh hoặc bất cứ điều gì khác. Đó là một định hướng hữu ích đôi khi.
foxxtrot

49
'-' không chỉ là quy ước git, mà là thứ bạn tìm thấy ở nhiều nơi trong dòng lệnh * nix. rm -- -f(loại bỏ một tập tin có tên -f) dường như là ví dụ điển hình. Chi tiết hơn tại đây
Hawkeye Parker

7
Chỉ cần thêm vào những gì @HawkeyeParker đã nói, rmlệnh sử dụng getopt (3) để phân tích các đối số của nó. getoptlà lệnh để phân tích các đối số lệnh. gnu.org/software/libc/manual/html_node/Getopt.html
Devy

2
@Honey Vâng, đó là những gì tôi muốn nói, và vâng, có lẽ không phổ biến chút nào. Tôi đã thấy ví dụ đó ở nhiều nơi, có lẽ chỉ để làm cho nó trở nên đáng nhớ: rm -f nổi tiếng là đáng sợ / nguy hiểm. Nhưng, vấn đề là, trong * nix, một tên tệp có thể bắt đầu bằng '-' và điều này sẽ gây nhầm lẫn cho các trình thông dịch dòng lệnh khác nhau, khi chúng thấy '-', sẽ có tùy chọn lệnh theo sau. Nó có thể là bất kỳ tệp nào bắt đầu bằng '-'; ví dụ: "-myecialFile".
Hawkeye Parker

288
git checkout -- foo

Điều đó sẽ thiết lập lại foothành CHÍNH. Bạn cũng có thể:

git checkout HEAD^ foo

cho một sửa đổi trở lại, vv


12
Tôi khuyên bạn nên sử dụng cú pháp git checkout -- foođể tránh mọi lỗi nếu foocó gì đặc biệt (như thư mục hoặc tệp được gọi -f). Với git, nếu bạn không chắc chắn, luôn luôn tiền tố tất cả các tệp và thư mục với đối số đặc biệt --.
Mikko Rantalainen

8
Một lưu ý bổ sung cho nhận xét của Mikko: --không phải là lệnh git và không đặc biệt đối với git. Nó là một bash tích hợp để biểu thị sự kết thúc của các tùy chọn lệnh. Bạn cũng có thể sử dụng nó với nhiều lệnh bash khác.
matthaeus

14
@matthaeus nó cũng không đặc trưng cho bash hay tính năng shell nào cả. Đó là một quy ước được thực hiện trong nhiều lệnh khác nhau (và được hỗ trợ bởi getopt).
Greg Hewgill

2
Không, --không một dựng sẵn từ đặc biệt trong bash. Nhưng đó là một quy ước chung được hỗ trợ bởi nhiều trình phân tích cú pháp dòng lệnh và được sử dụng bởi nhiều CLI, bao gồm cả git.
Emil Lundberg

123

Và để trở lại phiên bản cam kết cuối cùng, thường xuyên nhất, bạn có thể sử dụng lệnh đơn giản hơn này.

git checkout HEAD file/to/restore

2
sự khác biệt giữa cái này (git checkout tệp CHÍNH / đến / khôi phục) và git reset - tập tin / để / khôi phục ???
Motti Shneor

2
1) dễ nhớ hơn theo cách tổng quát hơn 2) không phải lo lắng khi nhấn Enter trước khi nhập tên tệp
Roman Susi

105

Tôi đã có cùng một vấn đề ngay bây giờ và tôi thấy câu trả lời này dễ hiểu nhất ( commit-reflà giá trị SHA của thay đổi trong nhật ký bạn muốn quay lại):

git checkout [commit-ref] [filename]

Điều này sẽ đưa phiên bản cũ đó vào thư mục làm việc của bạn và từ đó bạn có thể cam kết nó nếu bạn muốn.


91

Nếu bạn biết bạn cần quay lại bao nhiêu lần, bạn có thể sử dụng:

git checkout master~5 image.png

Điều này giả định rằng bạn đang ở masterchi nhánh và phiên bản bạn muốn là 5 cam kết trở lại.


80

Tôi nghĩ rằng tôi đã tìm thấy nó .... từ http://www-cs-students.stanford.edu/~blynn/gitmagic/ch02.html

Đôi khi bạn chỉ muốn quay lại và quên đi mọi thay đổi đã qua một điểm nhất định vì tất cả đều sai.

Bắt đầu với:

$ git log

trong đó hiển thị cho bạn một danh sách các cam kết gần đây và băm SHA1 của chúng.

Tiếp theo, gõ:

$ git reset --hard SHA1_HASH

để khôi phục trạng thái cho một cam kết nhất định và xóa tất cả các cam kết mới hơn khỏi bản ghi vĩnh viễn.


24
Git không bao giờ loại bỏ bất cứ điều gì. Cam kết cũ của bạn vẫn còn đó nhưng trừ khi có một đầu nhánh chỉ vào chúng, chúng không thể truy cập được nữa. git reflog vẫn sẽ hiển thị chúng cho đến khi bạn dọn sạch kho lưu trữ của mình bằng git-gc.
Bombe

1
@Bombe: Cảm ơn bạn đã thông tin. Tôi đã kiểm tra một phiên bản cũ của một tập tin. Sau khi đọc bình luận của bạn, tôi đã có thể sử dụng "gitref" để tra cứu hàm băm SHA1 một phần và sử dụng "thanh toán" để quay lại phiên bản mới nhất. Những người dùng git khác có thể thấy thông tin này hữu ích.
Winston C. Yang

4
có thể theo sau bởi mộtgit push --force
bshirley

4
Nếu bạn có những thay đổi không được cam kết, bạn sẽ mất chúng nếu thực hiện thiết lập lại git
hard

5
@Bombe - "Git không bao giờ xóa bất cứ thứ gì. Cam kết cũ của bạn vẫn còn nhưng trừ khi có một đầu nhánh chỉ vào chúng, chúng không thể truy cập được nữa." - nhưng các cam kết như thế này được cắt tỉa sau một thời gian định sẵn, vì vậy "Git không bao giờ xóa bất cứ thứ gì" là không đúng sự thật.
Bulwersator

61

Điều này làm việc cho tôi:

git checkout <commit hash> file

Sau đó cam kết thay đổi:

git commit -a

54

Bạn phải cẩn thận khi nói "rollback". Nếu bạn đã từng có một phiên bản của tệp trong cam kết $ A, và sau đó thực hiện hai thay đổi trong hai cam kết riêng biệt $ B và $ C (vì vậy những gì bạn đang thấy là lần lặp thứ ba của tệp) và nếu bạn nói " Tôi muốn quay trở lại cái đầu tiên ", bạn có thực sự muốn nói điều đó không?

Nếu bạn muốn loại bỏ các thay đổi cả lần lặp thứ hai và lần thứ ba, thì rất đơn giản:

$ git checkout $A file

và sau đó bạn cam kết kết quả. Lệnh hỏi "Tôi muốn kiểm tra tệp từ trạng thái được ghi bởi cam kết $ A".

Mặt khác, điều bạn muốn nói là loại bỏ thay đổi lần lặp thứ hai (tức là cam kết $ B) được đưa vào, trong khi vẫn giữ những gì cam kết $ C đã làm với tệp, bạn sẽ muốn hoàn nguyên $ B

$ git revert $B

Lưu ý rằng bất kỳ ai đã tạo cam kết $ B có thể không bị kỷ luật nhiều và có thể đã cam kết thay đổi hoàn toàn không liên quan trong cùng một cam kết và việc hoàn nguyên này có thể chạm vào các tệp khác với tệp bạn thấy các thay đổi vi phạm, vì vậy bạn có thể muốn kiểm tra kết quả cẩn thận sau khi thực hiện vì thế.


Tôi đã làm điều này, nhưng sau đó một "tệp nhật ký git" sẽ nói rằng tôi đã ở trên cam kết ban đầu, CHÍNH. Có vẻ như "kiểm tra git" đã thất bại. Tuy nhiên, trạng thái git cho thấy tệp đã thực sự thay đổi và "tệp git diff --staged" sẽ hiển thị các thay đổi thực tế. Ngoài ra, một "trạng thái git" cũng cho thấy tập tin đã thay đổi. Vì vậy, đừng sử dụng "git log" ở đây để theo dõi tập tin nào đã thay đổi.
Frederick Ollinger

37

Thật thú vị, git checkout foosẽ không hoạt động nếu bản sao làm việc nằm trong một thư mục có tên foo; tuy nhiên, cả hai git checkout HEAD foogit checkout ./foosẽ:

$ pwd
/Users/aaron/Documents/work/foo
$ git checkout foo
D   foo
Already on "foo"
$ git checkout ./foo
$ git checkout HEAD foo

26
hoặcgit checkout -- foo
knittl

32

Đây là cách rebasehoạt động:

git checkout <my branch>
git rebase master
git checkout master
git merge <my branch>

Giả sử bạn có

---o----o----o----o  master
    \---A----B       <my branch>

Hai lệnh đầu tiên ... cam kết kiểm tra git git rebase master

... kiểm tra chi nhánh thay đổi bạn muốn áp dụng cho masterchi nhánh. Các rebaselệnh có các cam kết từ <my branch>(không được tìm thấy trong master) và reapplies họ người đứng đầu master. Nói cách khác, cha mẹ của cam kết đầu tiên <my branch>không còn là một cam kết trước đó trong masterlịch sử, mà là người đứng đầu hiện tại master. Hai lệnh giống như:

git rebase master <my branch>

Có thể dễ dàng hơn để nhớ lệnh này vì cả hai nhánh "cơ sở" và "sửa đổi" đều rõ ràng.

. Kết quả lịch sử cuối cùng là:

---o----o----o----o   master
                   \----A'----B'  <my branch>

Hai lệnh cuối cùng ...

git checkout master
git merge <my branch>

... thực hiện hợp nhất chuyển tiếp nhanh để áp dụng tất cả các <my branch>thay đổi vào master. Không có bước này, cam kết rebase sẽ không được thêm vào master. Kết quả cuối cùng là:

---o----o----o----o----A'----B'  master, <my branch>

master<my branch>cả tài liệu tham khảo B'. Ngoài ra, từ thời điểm này, an toàn để xóa <my branch>tham chiếu.

git branch -d <my branch>

26

Kể từ git v2.23.0, có một phương pháp khôi phục git mới được cho là đảm nhận một phần git checkouttrách nhiệm (ngay cả câu trả lời được chấp nhận git checkoutcũng khá khó hiểu). Xem những điểm nổi bật của những thay đổi trên blog github .

Hành vi mặc định của lệnh này là khôi phục trạng thái của cây làm việc với nội dung đến từ sourcetham số (trong trường hợp của bạn sẽ là hàm băm cam kết).

Vì vậy, dựa trên câu trả lời của Greg Hewgill (giả sử hàm băm cam kết c5f567), lệnh sẽ giống như sau:

git restore --source=c5f567 file1/to/restore file2/to/restore

Hoặc nếu bạn muốn khôi phục lại nội dung của một cam kết trước c5f567:

git restore --source=c5f567~1 file1/to/restore file2/to/restore

24

Đầu đặt lại đầu tiên cho tệp mục tiêu

git reset HEAD path_to_file

Kiểm tra lần thứ hai tập tin đó

git checkout -- path_to_file

4
+1, mặc dù không chắc chắn về ý định đặt lại ĐẦU. Nó có thể hoặc không cần thiết. Trong tình huống của tôi, tôi chỉ muốn hoàn nguyên một tệp cụ thể về phiên bản trong kho lưu trữ (giữ nguyên các thay đổi cục bộ. Chỉ cần chạy bước thứ hai ở trên là đủ cho tôi
fkl

Có tôi chỉ cần chạy lệnh thứ 2. Giống như -> shellhacks.com/git-revert-file-to-preingly-commit
javaPlease42

22

git-aliases, awk và shell-function để giải cứu!

git prevision <N> <filename>

trong đó <N>số lượng bản sửa đổi của tệp để khôi phục cho tệp <filename>.
Ví dụ: để kiểm tra bản sửa đổi trước đó ngay lập tức của một tệp x/y/z.c, hãy chạy

git prevision -1 x/y/z.c

Làm thế nào git thịnh hành hoạt động?

Thêm phần sau vào gitconfig

[alias]
        prevision = "!f() { git checkout `git log --oneline $2 |  awk -v commit="$1" 'FNR == -commit+1 {print $1}'` $2;} ;f"

Lệnh cơ bản

  • thực hiện một git logtập tin được chỉ định và
  • chọn id xác nhận thích hợp trong lịch sử của tệp và
  • thực thi a git checkoutđến id xác thực cho tệp đã chỉ định.

Về cơ bản, tất cả những gì người ta sẽ làm thủ công trong tình huống này,
được gói gọn trong một bí danh git-alias đẹp, hiệu quả - git-thịnh hành


20

Tôi phải cắm EasyGit ở đây, đây là một trình bao bọc để giúp git dễ tiếp cận hơn với người mới mà không gây nhầm lẫn cho người dùng dày dạn kinh nghiệm. Một trong những điều nó làm là mang lại nhiều ý nghĩa hơngit revert . Trong trường hợp này, bạn chỉ cần nói:

eg revert foo/bar foo/baz


1
Nó phải eg revert --in REVISON -- FILENAME. Điều --inquan trọng. Đối với người dùng Windows ngoài kia: Mở git bash. Thực thi echo %PATH. Đường dẫn đầu tiên phải ở trong thư mục người dùng của bạn kết thúc bằng bin. Tạo đường dẫn đó. Cửa hàng ví dụ như có. Đặt tên cho nó eg. Không phải eg.txt.
koppor 2/12/2016

20

Trong trường hợp bạn muốn hoàn nguyên tệp về một cam kết trước đó (và tệp bạn muốn hoàn nguyên đã cam kết), bạn có thể sử dụng

git checkout HEAD^1 path/to/file

hoặc là

git checkout HEAD~1 path/to/file

Sau đó, chỉ cần giai đoạn và cam kết phiên bản "mới".

Được trang bị kiến ​​thức rằng một cam kết có thể có hai cha mẹ trong trường hợp hợp nhất, bạn nên biết rằng CHÍNH ^ 1 là cha mẹ đầu tiên và CHÍNH ~ 1 là cha mẹ thứ hai.

Hoặc sẽ hoạt động nếu chỉ có một cha mẹ trong cây.


19

Nhiều đề xuất ở đây, hầu hết dọc theo dòng git checkout $revision -- $file. Một vài lựa chọn thay thế tối nghĩa:

git show $revision:$file > $file

Ngoài ra, tôi sử dụng điều này rất nhiều chỉ để xem một phiên bản cụ thể tạm thời:

git show $revision:$file

hoặc là

git show $revision:$file | vim -R -

(OBS: $filecần phải được thêm tiền tố ./nếu đó là đường dẫn tương đối git show $revision:$fileđể làm việc)

Và điều kỳ lạ hơn nữa:

git archive $revision $file | tar -x0 > $file

1
Đây là một lựa chọn tốt nếu bạn không chắc chắn phiên bản cam kết nào bạn muốn và cần "nhìn trộm" xung quanh mà không ghi đè lên thư mục làm việc của bạn.
wvducky

18

Lưu ý, tuy nhiên, điều đó git checkout ./foogit checkout HEAD ./foo không hoàn toàn giống nhau; trường hợp tại điểm:

$ echo A > foo
$ git add foo
$ git commit -m 'A' foo
Created commit a1f085f: A
1 files changed, 1 insertions(+), 0 deletions(-)
create mode 100644 foo
$ echo B >> foo
$ git add foo
$ echo C >> foo
$ cat foo
A
B
C
$ git checkout ./foo
$ cat foo
A
B
$ git checkout HEAD ./foo
$ cat foo
A

( addGiai đoạn thứ hai tệp trong chỉ mục, nhưng nó không được cam kết.)

Git checkout ./foocó nghĩa là đường dẫn hoàn nguyên ./footừ chỉ mục ; việc thêm HEADhướng dẫn Git hoàn nguyên đường dẫn đó trong chỉ mục để HEADsửa đổi trước khi thực hiện.


14

Đối với tôi không có câu trả lời nào có vẻ thực sự rõ ràng và do đó tôi muốn thêm câu trả lời của tôi có vẻ siêu dễ dàng.

Tôi có một cam kết abc1và sau đó tôi đã thực hiện một vài (hoặc một sửa đổi) cho một tệp file.txt.

Bây giờ hãy nói rằng tôi đã làm hỏng một cái gì đó trong tệp file.txtvà tôi muốn quay lại cam kết trước đó abc1.

1 . git checkout file.txt: điều này sẽ loại bỏ các thay đổi cục bộ, nếu bạn không cần chúng

2 . git checkout abc1 file.txt: điều này sẽ đưa tập tin của bạn đến phiên bản mong muốn của bạn

3 . git commit -m "Restored file.txt to version abc1": điều này sẽ cam kết sự đảo ngược của bạn.

  1. git push : điều này sẽ đẩy mọi thứ trên kho lưu trữ từ xa

Giữa bước 2 và 3 tất nhiên bạn có thể làm git statusđể hiểu chuyện gì đang xảy ra. Thông thường bạn sẽ thấy file.txtđã được thêm vào và đó là lý do tại sao không cần a git add.


2
OK vì vậy tôi đoán các bước 1. và 2. loại trừ lẫn nhau: nếu abc1 là cam kết cuối cùng của bạn thì không cần 2. và nếu có các cam kết khác sau abc1, bạn có thể trực tiếp thực hiện 2.
Jean Paul

13
  1. Git hoàn nguyên tệp cho một cam kết cụ thể
git checkout Last_Stable_commit_Number -- fileName

2.Git hoàn nguyên tập tin đến một chi nhánh cụ thể

git checkout branchName_Which_Has_stable_Commit fileName

11

Để chuyển đến phiên bản cam kết trước đó của tệp, hãy lấy số cam kết, giả sử eb917a1 sau đó

git checkout eb917a1 YourFileName

Nếu bạn chỉ cần quay lại phiên bản được cam kết cuối cùng

git reset HEAD YourFileName
git checkout YourFileName

Điều này chỉ đơn giản sẽ đưa bạn đến trạng thái cam kết cuối cùng của tệp


10

kiểm tra git ref | commitHash - filePath

ví dụ

git checkout HEAD~5 -- foo.bar
or 
git checkout 048ee28 -- foo.bar

10

Nhiều câu trả lời ở đây tuyên bố sẽ sử dụng git reset ... <file>hoặc git checkout ... <file>bằng cách làm như vậy, bạn sẽ mất mọi sửa đổi đối với <file>cam kết sau khi cam kết bạn muốn hoàn nguyên.

Nếu bạn muốn hoàn nguyên các thay đổi từ một cam kết trên một tệp duy nhất, giống như git revertthực hiện nhưng chỉ với một tệp (hoặc nói một tập hợp con của các tệp cam kết), tôi khuyên bạn nên sử dụng cả hai git diffgit applynhư thế (với <sha>= hàm băm của cam kết bạn muốn hoàn nguyên):

git diff <sha>^ <sha> path/to/file.ext | git apply -R

Về cơ bản, trước tiên, nó sẽ tạo ra một bản vá tương ứng với những thay đổi bạn muốn hoàn nguyên, sau đó áp dụng ngược lại bản vá để loại bỏ những thay đổi đó.

Tất nhiên, nó sẽ không hoạt động nếu các dòng hoàn nguyên đã được sửa đổi bởi bất kỳ cam kết nào giữa <sha1>HEAD(xung đột).


Đó phải là câu trả lời được phê duyệt. Tôi có thể đề xuất một phiên bản đơn giản hơn một chút:git show -p <sha> path/to/file.ext|git apply -R
Amaury D

bạn có thể sử dụng <sha>^!thay vì<sha>^ <sha>
hẹn hò

8

Sử dụng git logđể lấy khóa băm cho phiên bản cụ thể và sau đó sử dụnggit checkout <hashkey>

Lưu ý: Đừng quên gõ băm trước cái cuối cùng. Hàm băm cuối cùng chỉ vị trí hiện tại của bạn (CHÍNH) và không thay đổi gì.


7

Rõ ràng ai đó cần phải viết một cuốn sách dễ hiểu về git, hoặc git cần được giải thích rõ hơn trong tài liệu. Đối mặt với vấn đề tương tự tôi đoán rằng

cd <working copy>
git revert master

sẽ hoàn tác cam kết cuối cùng dường như sẽ làm.

Ian


7

Bạn có thể làm điều đó trong 4 bước:

  1. hoàn nguyên toàn bộ cam kết với tệp bạn muốn hoàn nguyên cụ thể - nó sẽ tạo ra một cam kết mới trên nhánh của bạn
  2. thiết lập lại cam kết đó - loại bỏ cam kết và di chuyển các thay đổi đến khu vực làm việc
  3. chọn các tệp để hoàn nguyên và cam kết chúng
  4. thả tất cả các tập tin khác trong khu vực làm việc của bạn

Những gì bạn cần nhập vào thiết bị đầu cuối của bạn :

  1. git revert <commit_hash>
  2. git reset HEAD~1
  3. git add <file_i_want_to_revert> && git commit -m 'reverting file'
  4. git checkout .

chúc may mắn


điều đó không hoàn nguyên TẤT CẢ những thay đổi?
arcee123

1
@ arcee123 Có, nhưng thiết lập lại sau đó hoàn tác lại tất cả các thay đổi. Vấn đề là git-revertchỉ hoạt động trên toàn bộ repo, vì vậy để bù lại, chúng tôi phải hoàn tác mọi thứ khác.
Ti-mô-thê

2
Tôi khuyên bạn nên sử dụng: 1. git revert --no-commit <commit_hash>2. git reset HEADĐiều này sẽ lưu một cam kết bổ sung trôi nổi xung quanh và thực hiện tất cả các thay đổi chỉ trong thư mục làm việc của bạn.
Ti-mô-thê

Câu trả lời của @ greg-hewgill là tốt hơn và được chú ý. Điều này là tệ hại và không nên được sử dụng.
Daniel Tranca

Đây chính xác là những gì cần thiết cho một bản hoàn nguyên thực sự của các tệp cụ thể. Tôi cần hoàn tác các thay đổi đối với một vài tệp từ một cam kết trước đó đã được đẩy đến kho lưu trữ từ xa. Tôi đã hoàn nguyên, đặt lại và cam kết kết quả: git revert _oldcommit_ --no-commit git reset -- _unchanged1_ _unchanged2_ ... git commit -m "branch without changes to specific files"Đầu nhánh mới phản ánh tất cả các thay đổi ngoại trừ các tệp được hoàn nguyên.
Suncat2000

7

Đây là một bước rất đơn giản. Kiểm tra tệp vào id xác nhận mà chúng tôi muốn, ở đây một id xác nhận trước đó, sau đó chỉ cần git commit sửa đổi và chúng tôi đã hoàn tất.

# git checkout <previous commit_id> <file_name>
# git commit --amend

Điều này rất tiện dụng. Nếu chúng tôi muốn đưa bất kỳ tệp nào vào bất kỳ id xác nhận trước nào ở đầu cam kết, chúng tôi có thể dễ dàng thực hiện.


5
git revert <hash>

Sẽ hoàn nguyên một cam kết nhất định. Có vẻ như bạn nghĩ git revertchỉ ảnh hưởng đến cam kết gần đây nhất.

Điều đó không giải quyết được vấn đề của bạn, nếu bạn muốn hoàn nguyên một thay đổi trong một tệp cụ thể và cam kết đó đã thay đổi nhiều hơn tệp đó.


5

nếu bạn cam kết một tệp sai trong lần xác nhận cuối cùng của mình, hãy làm theo hướng dẫn:

  1. cây nguồn mở, thay đổi cam kết này

cây nguồn mở

  1. thay đổi các dòng và tìm cam kết của bạn rằng tệp sai được gửi dưới dạng cam kết

nhập mô tả hình ảnh ở đây

  1. bạn có thể xem danh sách các thay đổi của bạn trong cam kết đó danh sách các tập tin trong cây nguồn
  2. chọn nó và sau đó nhấp vào ... nút bên phải ... nhấp vào tập tin đảo ngược
  3. sau đó bạn có thể thấy nó trên tab trạng thái tệp ở phía dưới bên trái, sau đó nhấp vào unstage:

tab trạng thái tập tin

  1. mở mã phòng thu trực quan của bạn và hoàn nguyên lại bằng cách cam kết các tệp đã xóa của bạn
  2. sau tất cả, bạn có thể thấy kết quả trong lần xác nhận cuối cùng của mình trong cây nguồn

nhập mô tả hình ảnh ở đây

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.