Làm thế nào để unstash chỉ một số tập tin?


386

Tôi cất giấu những thay đổi của mình. Bây giờ tôi muốn hủy bỏ chỉ một số tệp từ stash. Tôi có thể làm cái này như thế nào?


4
Tôi nghĩ rằng bạn phải áp dụng toàn bộ stash, nhưng sau đó bạn có thể chọn lại stash.
Richard

4
@AbdouTahiri Điều gì là sai với stash?
alex

32
@AbdouTahiri Uhhhh .. git stash là một tính năng hợp pháp và cực kỳ hữu ích. Tôi sử dụng nó hàng ngày. Nói, một đồng nghiệp cần tôi xem xét một cái gì đó nhưng tôi đang ở giữa một bộ thay đổi phức tạp. Tôi sẽ không cam kết một đống mã bị hỏng chỉ để tôi có thể chuyển đổi chi nhánh. Tôi sẽ sắp xếp, chuyển đổi chi nhánh, xem xét, chuyển đổi lại, hủy bỏ. Bạn có quan tâm đến việc giải thích về ai hoặc tại sao git stash được cho là "không được đề xuất" không? Chỉ vì lịch sử git stit của bạn bị rối loạn và khó đọc không có nghĩa là mọi người đều thích. Một tập hợp git lộn xộn chỉ là quy trình công việc tồi tệ, không phải là một lỗ hổng của Git.
dudewad

6
@alex Không có gì. Không có gì là sai với git stash. Tiếp tục sử dụng nó.
dudewad

Câu trả lời:


461

Như được đề cập dưới đây và chi tiết trong " Làm cách nào tôi trích xuất một tệp duy nhất (hoặc thay đổi thành tệp) từ git stash? ", Bạn có thể áp dụng sử dụng git checkouthoặc git showkhôi phục một tệp cụ thể.

git checkout stash@{0} -- <filename>

Điều đó ghi đè lên filename : đảm bảo bạn không có sửa đổi cục bộ hoặc thay vào đó bạn có thể muốn hợp nhất tệp đã lưu .

(Theo nhận xét của Jaime M. , đối với một số shell nhất định như tcsh nơi bạn cần thoát các ký tự đặc biệt, cú pháp sẽ là git checkout 'stash@{0}' -- <filename>:)

hoặc để lưu nó dưới tên tệp khác:

git show stash@{0}:<full filename>  >  <newfile>

(lưu ý rằng đây <full filename>là tên đường dẫn đầy đủ của một tệp liên quan đến thư mục trên cùng của dự án (nghĩ: liên quan đến stash@{0})).

yucer gợi ý trong các ý kiến :

Nếu bạn muốn chọn thủ công những thay đổi bạn muốn áp dụng từ tệp đó:

git difftool stash@{0}..HEAD -- <filename>

Vivek thêm vào trong các ý kiến :

Có vẻ như " git checkout stash@{0} -- <filename>" khôi phục phiên bản của tệp tại thời điểm stash được thực hiện - nó KHÔNG áp dụng (chỉ) các thay đổi được lưu cho tệp đó.
Để làm sau:

git diff stash@{0}^1 stash@{0} -- <filename> | git apply

(như nhận xét của peterflynn , | git apply -p1trong một số trường hợp , bạn có thể cần xóa một ( p1) dấu gạch chéo hàng đầu khỏi đường dẫn khác biệt truyền thống)


Như đã nhận xét: "unstash" ( git stash pop), sau đó:

  • thêm những gì bạn muốn giữ vào chỉ mục ( git add)
  • cất phần còn lại: git stash --keep-index

Điểm cuối cùng là những gì cho phép bạn giữ một số tập tin trong khi đâm vào những người khác.
Nó được minh họa trong " Cách bỏ chỉ một tệp trong số nhiều tệp đã thay đổi ".


5
Điều này không hoạt động nếu bạn không thể git stash popdo xung đột tập tin. Câu trả lời của Balamurugan A đã lừa tôi trong trường hợp đó.
Andrey

1
Nếu bạn muốn chọn thủ công những thay đổi bạn muốn áp dụng từ tệp đó, bạn có thể sử dụng git Difftool stash @ {0} .. CHÍNH - <tên tệp>
yucer

5
Trông giống như "git checkout stash @ {0} - <tên tệp>" khôi phục phiên bản của tệp tại thời điểm stash được thực hiện - nó KHÔNG áp dụng (chỉ) các thay đổi được lưu cho tệp đó. Để thực hiện việc sau: "git diff stash @ {0} ^ 1 stash @ {0} - <tên tệp> | git áp dụng"
Vivek

1
@JaimeM. Cảm ơn bạn. Tôi đã bao gồm nhận xét của bạn trong câu trả lời để dễ nhìn hơn.
VonC

1
Giả sử điều đó unstashcó nghĩa pop, vì dường như với tôi rằng có lẽ trong hầu hết các trường hợp, điều này chỉ trả lời một phần câu hỏi. Sau đó, làm thế nào để bạn loại bỏ các phần được áp dụng có chọn lọc khỏi stash để tránh xung đột và / hoặc nhầm lẫn sau đó khi bật các thay đổi còn lại?
DylanYoung

115
git checkout stash@{N} <File(s)/Folder(s) path> 

Ví dụ. Để chỉ khôi phục tệp ./test.c và thư mục ./include từ lần lưu cuối cùng,

git checkout stash@{0} ./test.c ./include

12
Đây là câu trả lời chính xác! Lệnh một dòng để chỉ áp dụng các thay đổi được lưu trữ từ các tệp cụ thể, hoạt động như một nét duyên dáng!
4levels

1
Để áp dụng (chỉ) các thay đổi được lưu cho tệp: "git diff stash @ {N} ^ 1 stash @ {N} - <tên tệp> | git áp dụng"
Vivek

Điều này làm việc cho tôi quá. Chỉ cần chọn lọc kiểm tra các tập tin cần thiết để sử dụng từ stash và bạn đã hoàn thành. Tôi đã bị mắc kẹt trong đó tôi đã sử dụng -acờ trong khi tạo stash.
Rajeev Ranjan

1
@ 4levels Tôi nghĩ rằng "áp dụng thay đổi stash" không phải là điều xảy ra, phải không? Tôi nghĩ rằng "ghi đè bất cứ điều gì bạn có với bản sao từ stash" là điều xảy ra.
msouth

35

Tôi nghĩ rằng câu trả lời của VonC có thể là những gì bạn muốn, nhưng đây là một cách để thực hiện một "git áp dụng" có chọn lọc:

git show stash@{0}:MyFile.txt > MyFile.txt

4
Đây có thể là những gì bạn muốn trong một số trường hợp, nhưng hãy cẩn thận rằng lệnh này sẽ ghi đè thay vì hợp nhất với bất kỳ thay đổi thư mục làm việc.
Đại hoàng 5/11/2015

Điều này làm việc cho tôi, vì tôi chỉ muốn sao chép một tệp chỉ tồn tại trong stash và không quan tâm đến checkoutbất cứ điều gì.
Tom Russell

1
Đối với Windows PowerShell: git show stash@`{0`}:Path/To/MyFile.txt |sc Path/To/MyFile.txt- các backticks là cần thiết để PS không diễn giải các dấu ngoặc đặc biệt và điều scnày là cần thiết >toán tử của PS mặc định là UTF-16 (thực ra là UCS-2) có thể không phải là điều bạn muốn. @Balamurugan Câu trả lời của A không gặp phải những vấn đề này.
Ian Kemp

19

Danh sách đầu tiên tất cả các stash

git stash list

stash@{0}: WIP on Produktkonfigurator: 132c06a5 Cursor bei glyphicon plus und close zu zeigende Hand ändern
stash@{1}: WIP on Produktkonfigurator: 132c06a5 Cursor bei glyphicon plus und close zu zeigende Hand ändern
stash@{2}: WIP on master: 7e450c81 Merge branch 'Offlineseite'

Sau đó hiển thị tệp nào trong stash (cho phép chọn stash 1):

git stash show 1 --name-only

//Hint: you can also write
//git stash show stash@{1} --name-only

 ajax/product.php
 ajax/productPrice.php
 errors/Company/js/offlineMain.phtml
 errors/Company/mage.php
 errors/Company/page.phtml
 js/konfigurator/konfigurator.js

Sau đó áp dụng tệp bạn muốn:

git checkout stash@{1} -- <filename>

hoặc toàn bộ thư mục:

git checkout stash@{1} /errors

Nó cũng hoạt động mà không có --nhưng nên sử dụng chúng. Xem bài này .

Nó cũng là thông thường để nhận ra một dấu gạch nối kép như một tín hiệu để dừng giải thích tùy chọn và xử lý tất cả các đối số sau đây theo nghĩa đen.


1
Điều đó rõ ràng hơn với chỉnh sửa này. +1
VonC

1
Tôi đã thử nhiều cách và cách này là cách tôi cần. Tôi đã phải đối mặt với một vấn đề gây git stash popra lỗi cho các tập tin không được theo dõi. cảm ơn bạn.
Ramin Firooz

10

nếu bạn git stash pop (không có xung đột), nó sẽ xóa stash sau khi được áp dụng. Nhưng nếu bạn git stash applysẽ áp dụng bản vá mà không xóa nó khỏi danh sách stash. Sau đó, bạn có thể hoàn nguyên các thay đổi không mong muốn vớigit checkout -- files...


2
Để làm rõ phần xung đột của bài đăng này, nếu bạn git stash popvà có Mâu thuẫn, bạn sẽ phải sửa chúng bằng tay và stash sẽ KHÔNG bị xóa.
Thomas McCabe

6

Một cách nữa:

git diff stash@{N}^! -- path/to/file1 path/to/file2  | git apply -R

2
Đây là câu trả lời đúng duy nhất IMO. Sử dụng checkouthoặc showsẽ ghi đè lên tệp của bạn một cách mù quáng thay vì chỉ áp dụng các thay đổi. "Một cách nữa" là một cách đánh giá thấp.
quay cuồng

1
Tôi không nhận được path/to/file2như bạn muốn khác với cùng một tệp trong không gian làm việc của bạn. Rời khỏi con đường thứ hai hoạt động tốt cho tôi. - Và tôi nhận được một thông báo lỗi bằng cách sử dụng -Rtùy chọn ("áp dụng bản vá ngược lại", cố gắng vá phiên bản đã lưu?!). Vì vậy, phiên bản làm việc của tôi trông như thế git diff stash@{N}^! -- path/to/file | git apply -.
ThomasH

"vá lỗi"? Hãy thử hợp nhất 3 chiều. ...| git apply -3 -
John Mee

6

Đối với người dùng Windows: dấu ngoặc nhọn có ý nghĩa đặc biệt trong PowerShell. Bạn có thể bao quanh với dấu ngoặc đơn hoặc thoát với backtick. Ví dụ:

git checkout 'stash@{0}' YourFile

Không có nó, bạn có thể nhận được một lỗi:

Unknown switch 'e'


3
Đánh dấu đầy đủ vào PowerShell cho thông báo người dùng ít hữu ích nhất tôi đã thấy trong tháng này.
Holdenweb
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.