Git stash: Có thể áp dụng cho một cây làm việc bẩn thỉu, vui lòng thực hiện các thay đổi của bạn


133

Tôi đang cố gắng áp dụng các thay đổi mà tôi đã lưu trước đó git stash popvà nhận được thông báo:

Cannot apply to a dirty working tree, please stage your changes

Bất kỳ đề nghị về làm thế nào để đối phó với điều đó?

Câu trả lời:


196

Khi tôi phải áp dụng các thay đổi được lưu trữ cho một bản sao làm việc bẩn, ví dụ: bật nhiều hơn một thay đổi từ bản gốc, tôi sử dụng như sau:

$ git stash show -p | git apply -3 && git stash drop

Về cơ bản nó

  1. tạo ra một bản vá
  2. ống dẫn đến lệnh áp dụng
  3. nếu có bất kỳ xung đột nào, họ sẽ cần được giải quyết thông qua hợp nhất 3 chiều
  4. nếu áp dụng (hoặc hợp nhất) thành công, nó sẽ bỏ mục stash vừa áp dụng ...

Tôi tự hỏi tại sao không có -ftùy chọn (lực lượng) git stash popnào hoạt động chính xác như một lớp lót ở trên.

Trong thời gian chờ đợi, bạn có thể muốn thêm lớp lót này dưới dạng bí danh git:

$ git config --global --replace-all alias.unstash \
   '!git stash show -p | git apply -3 && git stash drop'
$ git unstash

Cảm ơn @SamHasler đã chỉ ra -3tham số cho phép giải quyết xung đột trực tiếp thông qua hợp nhất 3 chiều.


git stash show -p | git applykhác git stash applygì không?
Yếu tố huyền bí

1
Jo Factor, git stash applysẽ không áp dụng các thay đổi được lưu trữ nếu bạn có một bản sao làm việc bẩn. Vì vậy, bạn có thể thấy git stash show -p | git applynhư một số loại stash bắt buộc áp dụng.
muhqu

1
không giúp đỡ Nhưng giúp đỡ: git thiết lập lại CHÍNH và hủy bỏ các thay đổi sau đó.
Roger Alien

4
Tôi nhận được "lỗi: bản vá lỗi ... bản vá không áp dụng" cho một trong các tệp. Tôi muốn nó đã cho một cuộc xung đột hợp nhất.
Alexanderr Dubinsky

1
Giải pháp này không hiệu quả với tôi, nó đã thất bại với error: <file> does not match indexmọi tệp sửa đổi. Tuy nhiên, một giải pháp khác đã làm việc.
silvenon

57

Tôi làm theo cách này:

git add -A
git stash apply

và sau đó (tùy chọn):

git reset

2
+1! Điều này đơn giản hơn các giải pháp khác liên quan đến việc tạo các bản vá hoặc sửa đổi các cam kết và nó giữ cho các thay đổi cục bộ của bạn được cách ly an toàn với các thay đổi của ứng dụng cho đến khi bạn chắc chắn các thay đổi được hợp nhất.
peterflynn

Tôi gặp lỗi "... đã tồn tại, không có kiểm tra ... Không thể khôi phục các tệp không bị theo dõi từ stash"
Aleksandr Dubinsky

2
Tôi đã sử dụng git add -u, giống như -Angoại trừ nó không thêm các tệp không bị theo dõi.
Brad Cupit

9

Bạn có thể thực hiện việc này mà không cần phải bỏ các thay đổi hiện tại của mình bằng cách xuất stash bạn muốn dưới dạng tệp vá và áp dụng thủ công.

Ví dụ: giả sử bạn muốn áp dụng stash @ {0} cho cây bẩn:

  1. Xuất stash @ {0} dưới dạng bản vá:

    chương trình git stash -p stash @ {0}> Stash0.patch

  2. Áp dụng thủ công các thay đổi:

    git áp dụng Stash0.patch

Nếu bước thứ hai không thành công, bạn sẽ phải chỉnh sửa tệp Stash0.patch để sửa bất kỳ lỗi nào và sau đó thử git áp dụng lại.


Điều này là thực tế và khả thi đối với trường hợp, tôi đã thực hiện tái cấu trúc trên một thư mục (loại bỏ nó và tạo một liên kết tượng trưng với tên của nó). Git không thể cho biết những thay đổi bản sao làm việc của tôi là gì.
yclian

1
Điều này đã làm việc tuyệt vời. Tôi đã không thể áp dụng một stash mặc dù tôi khá chắc chắn rằng cây làm việc của tôi sạch sẽ.
Shiki

Có, tôi đã phải xóa các dòng về một tệp nhị phân.
Dorian

8

Làm sạch thư mục làm việc của bạn với git reset, cam kết các thay đổi hoặc, nếu bạn muốn xóa các thay đổi hiện tại, hãy thử:

$ git stash lưu "mô tả các thay đổi hiện tại"
$ git stash pop stash @ {1}

Điều này sẽ bỏ qua các thay đổi hiện tại, và sau đó bật ngăn thứ hai từ ngăn xếp.


5
Nhưng anh chàng này muốn hai stash áp dụng!
Elazar Leibovich

@Elazar Bạn đang đọc câu hỏi. OP chỉ muốn áp dụng một stash trước đó. Nếu bạn đúng rằng các thay đổi hiện tại sẽ được giữ, giải pháp có thể được lặp lại: pop, commit, lặp lại.
William Pursell

Tôi nghĩ rằng anh ấy muốn cả hai không được khuyến khích. Nhưng sau đó, một lần nữa, anh ta có thể cam kết hai lần và ép chúng thành một cam kết duy nhất.
Elazar Leibovich

Tôi gặp lỗi "... đã tồn tại, không có kiểm tra ... Không thể khôi phục các tệp không bị theo dõi từ stash"
Aleksandr Dubinsky

6

Giải pháp của Mathias chắc chắn là gần nhất với pop-stash pop - Force (và thực sự, đó là các nhà phát triển Git, chúng ta hãy có tùy chọn này!)

Tuy nhiên, nếu bạn muốn làm điều tương tự chỉ bằng các lệnh git, bạn có thể:

  1. git cam kết -a -m "Fixme"
  2. git stash pop
  3. cam kết -a --amend
  4. git đặt lại đầu ~

Nói cách khác, thực hiện một cam kết (mà chúng tôi sẽ không bao giờ thúc đẩy) các thay đổi hiện tại của bạn. Bây giờ không gian làm việc của bạn sạch sẽ, hãy bật stash của bạn. Bây giờ, cam kết thay đổi stash như là một sửa đổi cho cam kết trước đó của bạn. Hoàn thành rằng bây giờ bạn có cả hai bộ thay đổi được kết hợp trong một cam kết duy nhất ("Fixme"); chỉ cần đặt lại (--soft KHÔNG - vì vậy không có gì thực sự bị mất) thanh toán của bạn thành "một trước khi cam kết" và bây giờ bạn có cả hai bộ thay đổi, hoàn toàn không được cam kết.

** CHỈNH SỬA * *

Tôi chỉ nhận ra rằng nó thực sự thậm chí còn dễ dàng hơn; bạn hoàn toàn có thể bỏ qua bước 3, vì vậy ...

  1. git cam kết -a -m "Fixme"
  2. git stash pop
  3. git đặt lại đầu ~

(Cam kết các thay đổi hiện tại, tắt các thay đổi được lưu lại, đặt lại cam kết đầu tiên đó để có được cả hai bộ thay đổi được kết hợp ở trạng thái không được cam kết.)


4

Không có câu trả lời nào thực sự hiệu quả nếu bạn thấy mình trong tình huống này như tôi đã làm hôm nay. Bất kể git reset --hardtôi đã làm bao nhiêu , nó chẳng đưa tôi đến đâu. Câu trả lời của tôi (không chính thức bằng bất kỳ phương tiện nào là):

  1. Chỉ ra việc sử dụng hàm băm của stash git reflog --all
  2. Hợp nhất hàm băm đó với chi nhánh bạn quan tâm

1
Cảm ơn rất nhiều. Tôi đã thất vọng bởi cách Git cư xử kỳ lạ trên repo địa phương của tôi vừa rồi, cùng một vấn đề mà bạn mô tả.
yclian

4

Tôi cũng thấy giải pháp của Mathias Leppich hoạt động rất tốt vì vậy tôi đã thêm một bí danh cho nó vào .gitconfig toàn cầu của mình

[alias]
        apply-stash-to-dirty-working-tree = !git stash show -p | git apply && git stash drop

Bây giờ tôi chỉ có thể gõ

git apply-stash-to-dirty-working-tree

công việc tuyệt vời cho tôi

(Số dặm của bạn có thể thay đổi theo tên bí danh dài này. Nhưng tôi thích một mức độ dài dòng khi đi kèm với hoàn thành bash.)


3

Bạn có thể áp dụng một stash cho cây "bẩn" bằng cách thực hiện git addbất kỳ thay đổi nào bạn đã thực hiện, do đó làm sạch cây. Sau đó, bạn có thể git stash popvà áp dụng các thay đổi được lưu trữ, không có vấn đề.


2

Bạn có các tệp đã được sửa đổi nhưng không được cam kết. Hoặc:

git reset --hard HEAD (to bring everything back to HEAD)

hoặc, nếu bạn muốn lưu các thay đổi của mình:

git checkout -b new_branch
git add ...
git commit
git checkout -b old_branch
git stash pop

1
@MikeCooper - Tôi nghĩ rằng anh ta chỉ có nghĩa là thêm bất cứ điều gì bạn muốn thêm trước khi cam kết.
sscirrus

0

Tôi đã có cùng một vấn đề nhưng git không có tập tin thay đổi. Hóa ra tôi có một tệp index.lock đang nằm xung quanh. Xóa nó đã giải quyết vấn đề.


0

Tôi đã không thể có được hầu hết những thứ này để làm việc; vì một số lý do, nó luôn nghĩ rằng tôi có các thay đổi cục bộ đối với một tệp. Tôi không thể áp dụng stash, các bản vá sẽ không áp dụng checkoutreset --hardthất bại. Điều cuối cùng có hiệu quả là lưu stash như một nhánh với git stash branch tempbranchname, và sau đó thực hiện hợp nhất nhánh bình thường: git checkout mastergit merge tempbranchname. Từ http://git-scm.com/book/en/Git-Tools-Stashing :

Nếu bạn muốn một cách dễ dàng hơn để kiểm tra lại các thay đổi được lưu lại, bạn có thể chạy nhánh git stash, tạo ra một nhánh mới cho bạn, kiểm tra cam kết bạn đã thực hiện khi bạn thực hiện công việc của mình, áp dụng lại công việc của bạn ở đó và sau đó thả stash nếu áp dụng thành công

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.