Tại sao không thể áp dụng stash vào thư mục làm việc?


96

Tôi không thể áp dụng stash trở lại thư mục làm việc.

Chuyện nhỏ:

Đầu tiên, tôi đã cố gắng đẩy một số thay đổi đã cam kết, nhưng nó nói: "không, bạn không thể, hãy kéo trước" ... Được rồi, tôi sẽ lấy mọi thứ từ GitHub và sau đó đẩy các thay đổi của mình. Khi tôi cố gắng kéo, nó nói rằng tôi có các thay đổi sẽ bị ghi đè và tôi nên lưu trữ các thay đổi của mình. OK, tôi đã lưu trữ các thay đổi ... đã thực hiện kéo và đẩy các thay đổi đã cam kết. Nhưng bây giờ, tôi không thể khôi phục các thay đổi chưa cam kết mà tôi đang thực hiện.

Đây là lỗi:

MyPath/File.cs already exists, no checkout
Could not restore untracked files from stash

Chắc chắn rằng tôi vẫn chưa hiểu hết các khái niệm về git, chúng khiến tôi hơi bối rối ... có lẽ tôi đã làm sai điều gì đó.

Sẽ thật tuyệt nếu ai đó có thể giúp tôi giải quyết vấn đề này ... Tôi đã tìm kiếm trên google và mọi thứ trong hơn một giờ đồng hồ rồi mà vẫn chưa tìm ra giải pháp.

Giúp đỡ được nhiều đánh giá cao. Cảm ơn!

Câu trả lời:


74

Có vẻ như kho lưu trữ của bạn bao gồm một tệp chưa được kiểm soát mà sau đó đã được thêm vào kho lưu trữ. Khi bạn thử và kiểm tra, git ngay lập tức từ chối vì nó sẽ ghi đè lên một tệp hiện có.

Để khắc phục, bạn có thể làm điều gì đó như xóa tệp đó (không sao cả, nó vẫn còn trong kho lưu trữ), áp dụng kho lưu trữ của bạn và sau đó thay thế phiên bản đã lưu trữ của tệp bằng phiên bản trong kho lưu trữ nếu thích hợp.

Chỉnh sửa: Cũng có thể tệp chỉ được tạo trong cây làm việc mà không được thêm vào repo. Trong trường hợp này, không chỉ xóa tệp cục bộ, thay vào đó:

  1. chuyển nó đi nơi khác
  2. áp dụng kho
  3. hợp nhất hai phiên bản tệp theo cách thủ công (cây làm việc so với di chuyển).

2
Có cách nào để tôi có thể tránh phải lưu trữ mọi thứ trong tương lai ... Tôi đến từ SVN, và rất có thể xảy ra ... bạn chỉ cần cập nhật, giải quyết xung đột và sau đó cam kết. Git không thể khó đến mức tôi cần thêm 2 bước trong chu trình. Cảm ơn một lần nữa!
Miguel Angelo

2
@Miguel: Stashing không phải là một trở ngại. Đó là một công cụ bổ sung được cung cấp bởi Git cho phép bạn cải thiện quy trình làm việc của mình và tránh xung đột và cam kết không sạch sẽ. git-scm.com/docs/git-stash
Koraktor

8
Mặc dù câu trả lời là hợp lệ, tôi thực sự không chắc git là "chính xác" về điều này. Các tập tin nằm trong repo, vì vậy không có nguy cơ mất dữ liệu. tại sao không chỉ áp dụng các thay đổi? Xem chủ đề này - git.661346.n2.nabble.com/stash-refuses-to-pop-td7453780.html
studgeek

5
Tôi nghĩ câu trả lời này không phải là hữu ích nhất. git stashsẽ giúp nhanh chóng sao lưu các thay đổi cục bộ. Việc xóa thủ công một nhóm tệp để khôi phục nó sẽ phá vỡ quy trình. Cách git stash branchtiếp cận trong câu trả lời khác nghe có vẻ tốt hơn, nhưng vẫn thủ công hơn nhiều so với mong muốn.
màu bentolor

Câu trả lời này phù hợp nhất với tôi khi ở trong tình huống tương tự. Sau khi tôi xuất kho, tôi đã thực hiện một hợp nhất như tôi đã mong đợi ngay từ đầu.
Billy Lazzaro

58

Cách an toàn và dễ dàng nhất có lẽ là lưu trữ lại mọi thứ:

git stash -u             # This will stash everything, including unstaged files
git stash pop stash@{1}  # This will apply your original stash

Sau đó, nếu bạn hài lòng với kết quả, bạn có thể gọi

git stash drop

để xóa kho "an toàn" của bạn.


2
Cảm ơn bạn vì điều này, đã cứu tôi khỏi rất nhiều đau đớn và đau khổ!
danjarvis

9
stash pop sẽ áp dụng và giảm stash ban đầu của bạn. Chỉ để sử dụng an toàn applythay vì pop.
Hilbrand Bouwkamp

2
Trong thực tế, popnó là sự kết hợp của applydrop, nhưng sẽ chỉ dropkhi nó applyhoạt động mà không có xung đột. Nhưng có, applythường an toàn hơn.
Koraktor

2
Điều này giả định rằng không có thay đổi nào khác trong thư mục làm việc mà bạn muốn giữ lại. Đối với câu hỏi cụ thể này, anh ấy ngụ ý (nhưng không nói rõ ràng) anh ấy đang ở trong tình trạng trong sạch, nhưng tôi muốn chỉ ra điều đó cho những người khác đến đây với những thay đổi cục bộ.
studgeek

1
Điều này chỉ giải quyết vấn đề nếu các vấn đề xung đột chưa được cam kết . Bạn nhận được thông báo chính xác tương tự khi họ đã được cam kết (ví dụ với một kiểm sạch) và sau đó điều này sẽ không thay đổi điều gì ...
Jasper

56

Như đã đề cập bởi @bentolo, bạn có thể xóa thủ công các tệp mà nó đang phàn nàn, chuyển đổi các nhánh và sau đó thêm lại chúng theo cách thủ công. Nhưng cá nhân tôi thích ở "trong git" hơn.

Cách tốt nhất để làm điều này là chuyển kho lưu trữ thành một chi nhánh. Khi nó là một nhánh, bạn có thể làm việc bình thường trong git bằng cách sử dụng các kỹ thuật / công cụ liên quan đến nhánh thông thường mà bạn biết và yêu thích. Đây thực sự là một kỹ thuật chung hữu ích để làm việc với các kho lưu trữ ngay cả khi bạn không gặp lỗi được liệt kê. Nó hoạt động tốt bởi vì một kho lưu trữ thực sự là một cam kết dưới vỏ bọc (xem PS).

Chuyển đổi kho thành chi nhánh

Phần sau tạo một nhánh dựa trên HEAD khi kho lưu trữ được tạo và sau đó áp dụng kho lưu trữ (nó không cam kết).

git stash branch STASHBRANCH

Làm việc với "chi nhánh lưu trữ"

Những gì bạn làm tiếp theo phụ thuộc vào mối quan hệ giữa kho lưu trữ và chi nhánh mục tiêu của bạn (mà tôi sẽ gọi là ORIGINALBRANCH) hiện đang ở đâu.

Tùy chọn 1 - Rebase stash nhánh bình thường (rất nhiều thay đổi kể từ stash)

Nếu bạn đã thực hiện nhiều thay đổi trong ORIGINALBRANCH của mình, thì tốt nhất bạn nên xử lý STASHBRANCH giống như bất kỳ chi nhánh nào tại địa phương. Cam kết các thay đổi của bạn trong STASHBRANCH, căn cứ lại nó trên ORIGINALBRANCH, sau đó chuyển sang ORIGINALBRANCH và căn cứ lại / hợp nhất các thay đổi STASHBRANCH trên nó. Nếu có xung đột thì xử lý bình thường (một trong những ưu điểm của phương pháp này là bạn có thể nhìn thấy và giải quyết xung đột).

Tùy chọn 2 - Đặt lại nhánh ban đầu để khớp với kho (các thay đổi có giới hạn kể từ kho)

Nếu bạn chỉ lưu trữ trong khi giữ một số thay đổi theo giai đoạn, thì hãy cam kết và tất cả những gì bạn muốn làm là nhận được các thay đổi bổ sung mà bạn có thể làm như sau. Nó sẽ chuyển trở lại nhánh và chỉ mục ban đầu của bạn mà không thay đổi bản sao làm việc của bạn. Kết quả cuối cùng sẽ là các thay đổi kho lưu trữ bổ sung của bạn trong bản sao làm việc của bạn.

git symbolic-ref HEAD refs/heads/ORIGINALBRANCH
git reset

Lý lịch

Dấu gạch chéo là cam kết thích các nhánh / thẻ (không phải bản vá)

Tái bút, Thật là hấp dẫn khi nghĩ về một kho lưu trữ như một bản vá (giống như việc nghĩ về một cam kết như một bản vá) rất hấp dẫn, nhưng một kho lưu trữ thực sự là một cam kết chống lại HEAD khi nó được tạo. Khi bạn áp dụng / bật lên, bạn đang làm điều gì đó tương tự như hái quả anh đào vào chi nhánh hiện tại của bạn. Hãy nhớ rằng các nhánh và thẻ thực sự chỉ là các tham chiếu đến các cam kết, vì vậy theo nhiều cách, các dấu nháy, các nhánh và thẻ chỉ là các cách khác nhau để trỏ đến một cam kết (và lịch sử của nó).

Đôi khi cần ngay cả khi bạn chưa thực hiện thay đổi thư mục làm việc

PPS, Bạn có thể cần đến kỹ thuật này sau khi chỉ sử dụng kho với --patch và / hoặc --bao gồm-chưa được kiểm tra. Ngay cả khi không thay đổi thư mục làm việc, những tùy chọn này đôi khi có thể tạo ra một kho lưu trữ mà bạn không thể áp dụng lại. Tôi phải thừa nhận là không hoàn toàn hiểu tại sao. Xem http://git.661346.n2.nabble.com/stash-refuses-to-pop-td7453780.html để thảo luận.


5
Câu trả lời này nên được đánh dấu là giải pháp vì nó cung cấp các gợi ý hữu ích nhất về cách giải quyết 'kho bị khóa' hiệu quả nhất. Có thể cải thiện nó bằng cách đề cập đến 'giải pháp xóa đơn giản' đầu tiên và giải pháp nhánh là tùy chọn thứ hai.
bentolor

8
"git stash branch STASHBRANCH" dường như không hoạt động nếu bạn gặp phải trường hợp này (chính xác là cùng một thông báo lỗi xảy ra với pop). Bạn có thể phải thực hiện một số thiết lập lại git trước đó.

1 Tôi có bản thân mình trong một mớ hỗn độn mì spaghetti với cam kết và những thay đổi và stashing vv vv Điều này đã cho tôi ra khỏi nó bằng cách poping các stash đến một chi nhánh nhờ studgeek
RobbZ

Cảm ơn bạn đã giải thích rõ về cách lưu trữ không phải là bản vá và cách chúng được liên kết với HEAD (tại thời điểm lưu trữ). Điều đó làm cho rất nhiều ý nghĩa. - Vì vậy, ... Tôi cho rằng có những trường hợp linh hoạt / di động / thuận tiện hơn để tạo một bản vá hơn là một kho lưu trữ (như bạn đã đề cập: khi có nhiều thay đổi), để nó có thể được áp dụng ở bất cứ đâu (và là chỉ là vấn đề giải quyết xung đột). Có lẽ git stash show -pđang giúp đỡ để tạo kho -> * vá *.
Kamafeather

39

Giải pháp: Bạn cần xóa tệp được đề cập, sau đó thử lưu trữ pop / apply lại và nó sẽ hoàn thành. Không xóa các tệp khác, chỉ những tệp được đề cập bởi lỗi.

Vấn đề: Git đôi khi rất tệ. Khi chạy, git stash -unó bao gồm các tệp chưa được kiểm tra (tuyệt vời!) Nhưng nó không loại bỏ các tệp chưa được kiểm tra đókhông biết cách áp dụng các tệp chưa được kiểm tra đã lưu trữ lên trên phần còn lại (không hay!), Điều này thực sự làm cho -utùy chọn khá vô dụng.


3
Tôi sẽ chấp nhận câu trả lời này nếu đó là câu hỏi của tôi. Cảm ơn @qwertzguy, câu trả lời của bạn giải quyết vấn đề của tôi,
Kobus Myburgh

Bản thân tôi cũng gặp phải vấn đề tương tự, git stash pop sẽ không áp dụng cho đến khi tôi xóa các tệp được đề cập - sau đó tôi gặp xung đột với một tệp khiến kho lưu trữ bị từ chối. Nhưng thay vì sau đó loại bỏ các tập tin untracked nó để lại cho họ đằng sau .. Vì vậy, lưu ý đến tương lai tự nghỉ xagit stash -u
notzippy

Lời khuyên tồi nếu bạn cần các phần từ cả hai phiên bản của tệp bị ảnh hưởng.
Walf

2
"nó không xóa những tệp không được theo dõi" ... và không liệt kê chúng trong git stash show. Câu trả lời này đã làm cho bóng đèn sáng lên.
jscs 17/02/17

2
cộng với một cho Git đôi khi tệ.
Harish

29

Để áp dụng sự khác biệt mã trong kho lưu trữ dưới dạng bản vá, hãy sử dụng lệnh sau:

git stash show --patch | patch -p1

11
Thông thường, tốt hơn là giải thích một giải pháp thay vì chỉ đăng một số dòng mã ẩn danh. Bạn có thể đọc Làm thế nào để tôi viết một câu trả lời hay , và cả Giải thích các câu trả lời hoàn toàn dựa trên mã .
Massimiliano Kraus

Điều này phù hợp với tôi vì bản vá từ git stash show --patchkhông chứa các tệp chưa được theo dõi.
Steven Shaw

Câu trả lời này đã giúp tôi rất nhiều vì tôi không thể mở kho do có nhiều thay đổi trong kho của tôi kể từ khi kho được đẩy.
Erik Finnman

1

Điều này đã xảy ra với tôi rất nhiều lần, tôi lưu trữ các tệp không được theo dõi bằng git stash -u mà cuối cùng sẽ được thêm vào kho lưu trữ và tôi không thể áp dụng các thay đổi đã lưu trữ được nữa.

Tôi không thể tìm ra cách để buộc git stash pop/applythay thế các tệp, vì vậy trước tiên tôi xóa các bản sao cục bộ của các tệp chưa được kiểm tra đã được lưu trữ ( hãy cẩn thận vì nó sẽ xóa mọi thay đổi chưa được cam kết ) và sau đó áp dụng các thay đổi đã lưu trữ :

rm `git ls-tree -r stash@{0}^3 --name-only`
git stash apply

Cuối cùng, tôi sử dụng git status, git diffvà các công cụ khác để kiểm tra và bổ sung lại phần từ các tập tin bị loại bỏ nếu có điều gì đó mất tích.


Nếu bạn có những thay đổi chưa cam kết mà bạn muốn giữ lại, trước tiên bạn có thể tạo một cam kết tạm thời:

git add --all
git commit -m "dummy"
rm `git ls-tree -r stash@{0}^3 --name-only`
git stash apply

Sử dụng bất kỳ công cụ nào phù hợp với bạn để hợp nhất các thay đổi đã cam kết trước đó trở lại các tệp cục bộ và xóa cam kết giả:

git reset HEAD~1

0

Thao tác cửa sổ bật lên bị chặn tương tự của tôi là do các tệp bị bỏ qua còn sót lại (xem tệp .gitignore). Trạng thái Git hiển thị cho tôi được theo dõi và không được theo dõi, nhưng các hoạt động của tôi không xóa sạch các tệp bị bỏ qua.

Chi tiết: Tôi đã sử dụng git stash save -a, kiểm tra tổng thể để biên dịch và xem hoạt động ban đầu, sau đó cố gắng khôi phục tất cả để tiếp tục chỉnh sửa. Khi tôi kiểm tra chi nhánh của mình và cố gắng bật lên, các tệp bị bỏ qua của tôi vẫn ở đó từ trước khi lưu kho. Đó là bởi vì việc kiểm tra tổng thể chỉ ảnh hưởng đến các tệp đã cam kết - nó không xóa các tệp bị bỏ qua. Vì vậy, cửa sổ bật lên không thành công, về cơ bản nói rằng nó không muốn khôi phục các tệp bị bỏ qua đã lưu trữ của tôi trên đầu các tệp vẫn còn ở đó. Thật không may là tôi không thể tìm ra cách để bắt đầu một phiên hợp nhất với họ.

Cuối cùng, tôi đã sử dụng git clean -f -d -xđể xóa các tệp bị bỏ qua. Điều thú vị là trong số ~ 30 tệp của tôi, 4 tệp vẫn còn sau khi dọn dẹp (bị chôn vùi trong các thư mục con). Tôi sẽ phải tìm ra danh mục của chúng, và chúng phải được xóa theo cách thủ công.

Sau đó, pop của tôi đã thành công.



-1

Giải pháp khác:

cd to/root/your/project

# Show what git will be remove
git clean -n

# If all is good
git clean -f

# If not all is good, see
git clean --help

# Finish
git stash pop

Lỗi được đề cập trong câu hỏi là do một tệp tồn tại trong cả ngăn xếp và thư mục làm việc. Việc dọn dẹp chỉ khắc phục sự cố nếu tệp này không được theo dõi, điều này chắc chắn không phải lúc nào cũng xảy ra (và không phải trường hợp của OP, vì anh ta lấy tệp từ một lần kéo).
Xavier Poinas

-1

Với Git 2.14.x / 2.15 (Q3 2017), giải pháp của qwertzguy từ năm 2014 sẽ không còn cần thiết nữa.

Trước quý 3 năm 2017, bạn phải xóa tệp được đề cập, sau đó cố gắng lưu trữ pop / apply lại.
Với bản phát hành Git tiếp theo, bạn sẽ không phải làm điều đó.

Xem cam kết bbffd87 (11 tháng 8 năm 2017) bởi Nicolas Morey-Chaisemartin ( nmorey) .
(Hợp nhất bởi Junio ​​C Hamano - gitster- trong cam kết 0ca2f32 , 23 tháng 8 năm 2017)

stash: làm sạch các tệp không được theo dõi trước khi đặt lại

Nếu gọi git stash -utrên repo chứa tệp không bị bỏ qua nữa do sửa đổi gitignoretệp hiện tại , tệp này được lưu trữ nhưng không bị xóa khỏi cây làm việc.
Điều này là do git-stashtrước tiên bạn thực hiện thao reset --hardtác xóa .gitignoresửa đổi tệp và sau đó gọi git clean, để tệp không bị ảnh hưởng.
Điều này gây ra git stash poplỗi do tệp hiện có .

Bản vá này chỉ đơn giản là chuyển đổi thứ tự giữa làm sạch và đặt lại và thêm một bài kiểm tra cho usecase này.


-1

Cách an toàn nhất để theo dõi lưu trữ

git stash -u

Điều này sẽ lưu trữ tất cả bao gồm cả thay đổi chưa phân giai đoạn

git stash drop

sau khi bạn hoàn thành công việc, để xóa kho "an toàn" của bạn.


Như đã giải thích trong stackoverflow.com/a/23743125/6309 , điều đó không phải lúc nào cũng hoạt động với Git 2.14 trở xuống. Nó sẽ hoạt động với Git 2.15: stackoverflow.com/a/46027357/6309
VonC
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.