Git simpanan: "Tidak dapat diterapkan ke pohon kerja yang kotor, harap lakukan perubahan Anda"

133

Saya mencoba menerapkan perubahan yang saya sembunyikan sebelumnya git stash popdan menerima pesan:

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

Ada saran tentang bagaimana menghadapinya?

avernet
sumber

Jawaban:

196

Ketika saya harus menerapkan perubahan simpanan ke copy pekerjaan kotor, mis. Pop lebih dari satu perubahan dari simpanan, saya menggunakan yang berikut ini:

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

Pada dasarnya itu

  1. membuat tambalan
  2. pipa itu ke perintah apply
  3. jika ada konflik mereka perlu diselesaikan melalui penggabungan 3 arah
  4. jika menerapkan (atau menggabungkan) berhasil menjatuhkan item simpanan yang baru saja diterapkan ...

Saya bertanya-tanya mengapa tidak ada -fopsi (kekuatan) git stash popyang harus tepat berperilaku seperti liner satu di atas.

Sementara itu, Anda mungkin ingin menambahkan one-liner ini sebagai alias git:

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

Terima kasih kepada @SamHasler karena menunjukkan -3parameter yang memungkinkan untuk menyelesaikan konflik secara langsung melalui penggabungan 3 arah.

muhqu
sumber
Apakah git stash show -p | git applyberbeda dari git stash apply?
Factor Mystic
1
Jo Factor, git stash applytidak akan menerapkan perubahan simpanan jika Anda memiliki copy pekerjaan yang kotor. Jadi, Anda bisa melihatnya git stash show -p | git applysebagai semacam simpanan paksa yang berlaku.
muhqu
1
tidak membantu tetapi membantu: git atur ulang HEAD dan lepaskan perubahan setelah itu.
Roger Alien
4
Saya mendapatkan "kesalahan: tambalan gagal ... tambalan tidak berlaku" untuk salah satu file. Saya berharap itu memberi konflik gabungan.
Aleksandr Dubinsky
1
Solusi ini tidak berfungsi untuk saya, gagal error: <file> does not match indexuntuk setiap file yang dimodifikasi. Namun, solusi lain berhasil.
silvenon
57

Saya melakukannya dengan cara ini:

git add -A
git stash apply

dan kemudian (opsional):

git reset
Sergii Mostovyi
sumber
2
+1! Ini lebih sederhana daripada solusi lain yang melibatkan menghasilkan tambalan atau mengubah komitmen, dan itu membuat perubahan lokal Anda aman dari perubahan simpanan yang diterapkan sampai Anda yakin perubahan digabungkan dengan benar.
peterflynn
Saya mendapatkan kesalahan "... sudah ada, tidak ada checkout ... Tidak dapat mengembalikan file yang tidak terlacak dari simpanan"
Aleksandr Dubinsky
2
Saya menggunakan git add -u, yang seperti -Akecuali itu tidak menambahkan file yang tidak terlacak.
Brad Cupit
9

Anda dapat melakukan ini tanpa harus menyimpan perubahan Anda saat ini dengan mengekspor simpanan yang Anda inginkan sebagai file patch dan menerapkannya secara manual.

Misalnya, Anda ingin menerapkan simpanan @ {0} ke pohon kotor:

  1. Ekspor simpanan @ {0} sebagai tambalan:

    git stash show -p stash @ {0}> Stash0.patch

  2. Terapkan perubahan secara manual:

    git menerapkan Stash0.patch

Jika langkah kedua gagal, Anda harus mengedit file Stash0.patch untuk memperbaiki kesalahan dan kemudian mencoba git menerapkan lagi.

Ishan
sumber
Ini praktis dan bisa diterapkan untuk kasus itu, saya membuat refactoring pada direktori (menghapusnya, dan membuat symlink dengan namanya). Git tidak tahu apa perubahan copy pekerjaan saya.
yclian
1
Ini bekerja dengan baik. Saya tidak dapat menerapkan simpanan meskipun saya cukup yakin pohon kerja saya bersih.
Shiki
Ya, saya harus menghapus baris tentang file biner.
Dorian
8

Bersihkan direktori kerja Anda dengan git reset, lakukan perubahan, atau, jika Anda ingin menyembunyikan perubahan saat ini, cobalah:

simpanan $ git simpan "deskripsi perubahan saat ini"
$ git simpanan pop simpanan @ {1}

Ini akan menyembunyikan perubahan saat ini, dan kemudian memunculkan simpanan kedua dari tumpukan simpanan.

William Pursell
sumber
5
Tapi orang ini ingin kedua simpanan diterapkan!
Elazar Leibovich
@ Elazar Anda membaca pertanyaan. OP hanya ingin menerapkan simpanan sebelumnya. Jika Anda benar bahwa perubahan saat ini harus disimpan, solusinya dapat diulang: pop, komit, ulangi.
William Pursell
Saya pikir dia ingin mereka berdua tidak terikat. Tetapi sekali lagi, ia dapat melakukan dua kali dan menekan mereka menjadi satu komit.
Elazar Leibovich
Saya mendapatkan kesalahan "... sudah ada, tidak ada checkout ... Tidak dapat mengembalikan file yang tidak terlacak dari simpanan"
Aleksandr Dubinsky
6

Solusi Mathias jelas yang paling dekat dengan pop git - force (dan sungguh, ayolah Git devs, mari kita dapatkan opsi ini!)

Namun, jika Anda ingin melakukan hal yang sama hanya menggunakan perintah git, Anda dapat:

  1. git commit -a -m "Fixme"
  2. git stash pop
  3. git commit -a --amend
  4. git atur ulang KEPALA ~

Dengan kata lain, buat komitmen (yang tidak akan kami dorong) dari perubahan Anda saat ini. Sekarang ruang kerja Anda bersih, letakan simpanan Anda. Sekarang, komit simpanan perubahan sebagai amandemen terhadap komit Anda sebelumnya. Setelah melakukannya, Anda sekarang memiliki kedua set perubahan yang digabungkan dalam satu komit ("Fixme"); cukup reset (--soft NOT --hard jadi tidak ada yang benar-benar hilang) checkout Anda ke "satu sebelum komit", dan sekarang Anda memiliki kedua set perubahan, sepenuhnya tidak berkomitmen.

** EDIT * *

Saya baru sadar itu sebenarnya lebih mudah; Anda dapat melewati langkah 3, jadi ...

  1. git commit -a -m "Fixme"
  2. git stash pop
  3. git atur ulang KEPALA ~

(Komit perubahan saat ini, matikan perubahan yang disimpan, atur ulang komit pertama untuk menggabungkan kedua set perubahan dalam kondisi tidak berkomitmen.)

machineghost
sumber
4

Tidak satu pun dari jawaban ini yang benar-benar berfungsi jika Anda menemukan diri Anda dalam situasi ini seperti yang saya lakukan hari ini. Terlepas dari berapa banyak yang git reset --hardsaya lakukan, itu tidak berhasil. Jawaban saya (tidak resmi dengan cara apa pun adalah):

  1. Mencari tahu penggunaan hash simpanan git reflog --all
  2. Gabungkan hash dengan cabang yang Anda minati
Dan Rosenstark
sumber
1
Terima kasih banyak Yar. Saya frustrasi dengan bagaimana Git bertingkah aneh pada repo lokal saya barusan, masalah yang sama seperti yang Anda gambarkan.
yclian
4

Saya juga menemukan solusi Mathias Leppich untuk bekerja dengan baik sehingga saya menambahkan alias untuk itu ke global .gitconfig

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

Sekarang saya bisa mengetik

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

yang bekerja bagus untuk saya.

(Jarak tempuh Anda mungkin berbeda pada nama alias yang panjang ini. Tapi saya suka dosis verbositas ketika dilengkapi dengan bash completion.)

tikar
sumber
3

Anda dapat menerapkan simpanan ke pohon "kotor" dengan melakukan a git adduntuk membuat perubahan apa pun yang telah Anda buat, sehingga membersihkan pohon. Lalu Anda bisa git stash popdan menerapkan perubahan simpanan, tidak ada masalah.

Chris Vandevelde
sumber
2

Anda memiliki file yang telah dimodifikasi tetapi tidak dilakukan. Antara:

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

atau, jika Anda ingin menyimpan perubahan Anda:

git checkout -b new_branch
git add ...
git commit
git checkout -b old_branch
git stash pop
brool
sumber
1
@ MikeCooper - Saya pikir dia hanya bermaksud menambahkan apa pun yang ingin Anda tambahkan sebelum melakukan.
sscirrus
0

Saya memiliki masalah yang sama tetapi git tidak mengubah file. Ternyata saya punya file index.lock yang tergeletak di sekitar. Menghapusnya memecahkan masalah.

kemas
sumber
0

Saya tidak bisa mendapatkan sebagian besar dari ini untuk bekerja; untuk beberapa alasan selalu berpikir saya memiliki perubahan lokal ke file. Saya tidak bisa menerapkan simpanan, tambalan tidak akan berlaku, checkoutdan reset --hardgagal. Yang akhirnya berhasil adalah menyimpan simpanan sebagai cabang dengan git stash branch tempbranchname, dan kemudian melakukan penggabungan cabang normal: git checkout masterdan git merge tempbranchname. Dari http://git-scm.com/book/en/Git-Tools-Stashing :

Jika Anda ingin cara yang lebih mudah untuk menguji perubahan simpanan lagi, Anda dapat menjalankan git stash branch, yang menciptakan cabang baru untuk Anda, memeriksa komit yang Anda gunakan saat menyimpan pekerjaan Anda, mengajukan kembali pekerjaan Anda di sana, dan kemudian menjatuhkan simpanan jika berhasil diterapkan

rwilson04
sumber