Câu hỏi Hoàn tác sửa đổi bản sao làm việc của một tệp trong Git?


Sau lần commit cuối cùng, tôi đã sửa đổi một loạt các tệp trong bản sao làm việc của mình, nhưng tôi muốn hoàn tác các thay đổi đối với một trong các tệp đó, như trong việc đặt lại nó thành trạng thái giống như lần commit gần đây nhất.

Tuy nhiên, tôi chỉ muốn hoàn tác các thay đổi bản sao làm việc của chỉ một tệp mà thôi, không có gì khác với nó.

Làm thế nào để làm điều đó?


1297
2018-03-28 05:09


gốc




Các câu trả lời:


Bạn có thể dùng

git checkout -- file

Bạn có thể làm điều đó mà không cần -- (như đề xuất bởi nimrodm), nhưng nếu tên tệp trông giống như một chi nhánh hoặc thẻ (hoặc định danh sửa đổi khác), nó có thể bị lẫn lộn, vì vậy sử dụng -- là tốt nhất.

Bạn cũng có thể xem phiên bản cụ thể của tệp:

git checkout v1.2.3 -- file         # tag v1.2.3
git checkout stable -- file         # stable branch
git checkout origin/master -- file  # upstream master
git checkout HEAD -- file           # the version from the most recent commit
git checkout HEAD^ -- file          # the version before the most recent commit

1793
2018-03-28 06:12



sự khác nhau giữa HEAD và HEAD ^ là gì? - hasen
HEAD là cam kết mới nhất trên nhánh hiện tại và HEAD ^ là cam kết trước đó trên nhánh hiện tại. Đối với tình huống bạn mô tả, bạn có thể sử dụng git checkout HEAD - tên tệp. - Paul
Trong ngắn hạn "git checkout sha-reference - filename" trong đó tham chiếu sha là tham chiếu đến sha của một commit, dưới mọi hình thức (branch, tag, parent, etc.) - Lakshman Prasad
LƯU Ý: Nếu tệp đã được dàn dựng, trước tiên bạn cần đặt lại tệp. git reset HEAD <filename> ; git checkout -- <filename> - Olie
@ gwho Có, bạn có thể làm HEAD^^ cho 2 cam kết từ gần đây nhất, hoặc HEAD^^^ cho 3 cam kết trở lại. Bạn cũng có thể dùng HEAD~2, hoặc là HEAD~3, sẽ thuận tiện hơn nếu bạn muốn quay lại nhiều cam kết hơn, trong khi HEAD^2có nghĩa là "cha mẹ thứ hai của cam kết này"; vì các cam kết hợp nhất, một cam kết có thể có nhiều hơn một cam kết trước đó, vì vậy với HEAD^ một số lựa chọn của những người cha mẹ, trong khi với HEAD~ một số luôn chọn cha mẹ đầu tiên nhưng số lượng cam kết đó lại. Xem git help rev-parse để biết thêm chi tiết. - Brian Campbell


git checkout <commit> <filename>

Tôi sử dụng điều này ngày hôm nay bởi vì tôi nhận ra rằng favicon của tôi đã được ghi đè một vài cam kết trước khi tôi upgrated để drupal 6,10, vì vậy tôi đã có để có được nó trở lại. Đây là những gì tôi đã làm:

git checkout 088ecd favicon.ico

115
2018-03-28 10:25



Làm thế nào để có được cam kết (của một tập tin đã xóa trước đó), ngoại trừ di chuyển ném tấn "git log --stat" đầu ra? - Alex
IMO nó là loại khó khăn thông qua các dòng lệnh để quét thông qua gits đăng nhập và tìm thấy các tập tin bên phải. Nó dễ dàng hơn nhiều với một ứng dụng GUI, chẳng hạn như sourcetreeapp.com - neoneye
git log --oneline <filename> sẽ cung cấp cho bạn nhật ký nhỏ gọn hơn và chỉ bao gồm các thay đổi đối với tệp cụ thể - rjmunro
cách khác, bạn có thể sử dụng git reflog <filename> - ygesher


Chỉ dùng

git checkout filename

Thao tác này sẽ thay thế tên tệp bằng phiên bản mới nhất từ ​​nhánh hiện tại.

CẢNH BÁO: các thay đổi của bạn sẽ bị hủy - không có bản sao lưu nào được lưu giữ.


101
2018-03-28 05:55



những gì là - cho? - Patoshi パトシ
@duckx nó là để phân biệt tên chi nhánh từ tên tập tin. nếu bạn nói git checkout x và x xảy ra là tên chi nhánh cũng như tên tệp, tôi không chắc chắn hành vi mặc định là gì nhưng tôi nghĩ git sẽ giả sử bạn muốn chuyển sang nhánh x. Khi bạn sử dụng -- bạn đang nói rằng những gì sau đây là tên tập tin (s). - hasen
ic cảm ơn cho thanh toán bù trừ mà lên. tất cả mọi người chỉ giả định bạn biết những gì - có nghĩa là khi họ cho bạn thấy ví dụ. và nó không phải cái gì bạn có thể google dễ dàng quá. - Patoshi パトシ
Có vẻ như câu trả lời đã được chỉnh sửa để xóa -- từ nó. Mặc dù vẫn chính xác, như @hasen chỉ ra, nếu có sự mơ hồ giữa tên tệp và tên chi nhánh, bạn có thể kết thúc với hành vi rất không mong muốn ở đây! - BrainSlugs83
Tôi thích nó theo cách của nó, mà không --, tốt đẹp và dễ dàng. Khi bạn đặt tên cho các nhánh bằng cách sử dụng tên tập tin, phải có suy nghĩ xấu ở đâu đó ... - Marco Faustinelli


Nếu tệp của bạn đã được dàn dựng (xảy ra khi bạn thực hiện git add etc sau khi tập tin được chỉnh sửa) để unstage thay đổi của bạn.

Sử dụng

git reset HEAD <file>

Sau đó

git checkout <file>

Nếu chưa được dàn dựng, chỉ cần sử dụng

git checkout <file>

52
2017-07-03 05:46



Điều này đã hữu ích hơn haha. Thật dễ dàng để quên những thay đổi đã được dàn dựng và những gì đã không, do đó, đặt lại giúp đỡ. Mặc dù tôi cũng đã thử "git reset --hard" trước đây, nó không làm những gì "git reset HEAD" đã làm. Tôi tự hỏi tại sao? - Arman Bimatov


Nếu bạn chỉ muốn hoàn tác các thay đổi của cam kết trước đó cho một tệp đó, bạn có thể thử điều này:

git checkout branchname^ filename

Điều này sẽ kiểm tra các tập tin như nó đã được trước khi cam kết cuối cùng. Nếu bạn muốn quay lại thêm một vài cam kết, hãy sử dụng branchname~n ký hiệu.


15
2018-03-28 05:25



Điều này sẽ không loại bỏ các thay đổi từ cam kết, nó sẽ chỉ áp dụng sự khác biệt cho phiên bản trên HEAD. - FernandoEscher
Trong khi đúng, poster gốc chỉ muốn hoàn nguyên các sửa đổi bản sao làm việc của mình (tôi nghĩ), không hoàn nguyên các thay đổi từ lần commit cuối cùng. Câu hỏi của poster ban đầu là một chút không rõ ràng, vì vậy tôi có thể hiểu được sự nhầm lẫn.


Tôi luôn bị lẫn lộn với điều này, vì vậy đây là một trường hợp kiểm tra nhắc nhở; giả sử chúng ta có cái này bash kịch bản để kiểm tra git:

set -x
rm -rf test
mkdir test
cd test
git init
git config user.name test
git config user.email test@test.com
echo 1 > a.txt
echo 1 > b.txt
git add *
git commit -m "initial commit"
echo 2 >> b.txt
git add b.txt
git commit -m "second commit"
echo 3 >> b.txt

Tại thời điểm này, thay đổi không được tổ chức trong bộ nhớ cache, vì vậy git status Là:

$ git status
On branch master
Changes not staged for commit:
  (use "git add <file>..." to update what will be committed)
  (use "git checkout -- <file>..." to discard changes in working directory)

    modified:   b.txt

no changes added to commit (use "git add" and/or "git commit -a")

Nếu từ thời điểm này, chúng tôi git checkout, kết quả là:

$ git checkout HEAD -- b.txt
$ git status
On branch master
nothing to commit, working directory clean

Nếu thay vào đó chúng ta làm git reset, kết quả là:

$ git reset HEAD -- b.txt
Unstaged changes after reset:
M   b.txt
$ git status
On branch master
Changes not staged for commit:
  (use "git add <file>..." to update what will be committed)
  (use "git checkout -- <file>..." to discard changes in working directory)

    modified:   b.txt

no changes added to commit (use "git add" and/or "git commit -a")

Vì vậy, trong trường hợp này - nếu các thay đổi không được tổ chức, git reset không có sự khác biệt, trong khi git checkout ghi đè các thay đổi.


Bây giờ, giả sử thay đổi cuối cùng từ tập lệnh trên được tổ chức / lưu vào bộ nhớ cache, đó là để nói rằng chúng tôi cũng đã làm git add b.txt cuối cùng.

Trong trường hợp này, git status tại thời điểm này là:

$ git status
On branch master
Changes to be committed:
  (use "git reset HEAD <file>..." to unstage)

    modified:   b.txt

Nếu từ thời điểm này, chúng tôi git checkout, kết quả là:

$ git checkout HEAD -- b.txt
$ git status
On branch master
nothing to commit, working directory clean

Nếu thay vào đó chúng ta làm git reset, kết quả là:

$ git reset HEAD -- b.txt
Unstaged changes after reset:
M   b.txt
$ git status
On branch master
Changes not staged for commit:
  (use "git add <file>..." to update what will be committed)
  (use "git checkout -- <file>..." to discard changes in working directory)

    modified:   b.txt

no changes added to commit (use "git add" and/or "git commit -a")

Vì vậy, trong trường hợp này - nếu các thay đổi được tổ chức, git reset về cơ bản sẽ thực hiện các thay đổi theo giai đoạn thành những thay đổi không được tổ chức - trong khi git checkout sẽ ghi đè hoàn toàn các thay đổi.


7
2018-02-09 08:56





Tôi khôi phục các tệp của mình bằng cách sử dụng id SHA, những gì tôi làm là git checkout <sha hash id> <file name>


5
2018-05-22 20:39