Saya memiliki banyak perubahan bertahap dan tidak bertahap dan saya ingin segera beralih ke cabang lain dan kemudian beralih kembali.
Jadi saya melakukan perubahan saya menggunakan:
$ git stash push -a
(Kalau dipikir-pikir, saya mungkin bisa menggunakan --include-untracked
alih-alih --all
)
Kemudian ketika saya pergi untuk membuka simpanan saya mendapatkan banyak kesalahan di sepanjang baris:
$ git stash pop
foo.txt already exists, no checkout
bar.txt already exists, no checkout
...
Could not restore untracked files from stash entry
Sepertinya tidak ada perubahan apa pun yang dipulihkan dari simpanan.
Saya juga mencoba $ git stash branch temp
tetapi itu menunjukkan kesalahan yang sama.
Saya memang menemukan cara untuk mengatasinya yang akan digunakan:
$ git stash show -p | git apply
Bencana dapat dihindari untuk saat ini, tetapi ini menimbulkan beberapa pertanyaan.
Mengapa kesalahan ini terjadi sejak awal dan bagaimana cara menghindarinya di lain waktu?
git stash show -p | git apply --3
git stash show
dan dari file penyelamatan satu per satu:$ git show stash@{0}:your/stashed/file.txt > your_rescued_file.txt
. Ini akan mengambil file dari simpanan dan menyimpannya dengan nama yang berbeda. Sekarang Anda aman untuk bereksperimen dengan metode penyelamatan yang tepat (lihat jawaban di bawah). Jika ada yang tidak beres, Anda selalu memiliki file yang diselamatkan sebagai sumber daya terakhir.Jawaban:
Sebagai sedikit penjelasan tambahan, catatan yang
git stash
membuat dua komit, atau tiga komit. Defaultnya adalah dua; Anda mendapatkan tiga jika Anda menggunakan ejaan--all
atau--include-untracked
opsi.Dua, atau tiga, komit ini istimewa dalam satu hal penting: tidak ada cabang. Git menempatkannya melalui nama khusus
stash
. 1 Namun, hal terpenting adalah apa yang Git izinkan untuk Anda — dan buat Anda — lakukan dengan dua atau tiga komitmen ini. Untuk memahami hal ini kita perlu melihat apa yang ada di dalam commit tersebut.Apa yang ada di dalam simpanan
Setiap komit bisa mendaftar satu atau lebih komit orang tua . Ini membentuk grafik, di mana kemudian komitmen menunjuk kembali ke yang sebelumnya. Stash biasanya menampung dua komit, yang ingin saya panggil
i
untuk konten index / staging-area, danw
untuk konten work-tree. Ingat juga bahwa setiap komit menyimpan sebuah snapshot. Dalam komit normal, snapshot ini dibuat dari konten index / staging-area. Jadii
komit sebenarnya adalah komit normal sempurna! Hanya saja tidak di cabang mana pun:Jika Anda membuat simpanan normal,
git stash
kodenyaw
sekarang dengan menyalin semua file pohon kerja terlacak Anda (ke dalam indeks tambahan sementara). Git menetapkan orang tua pertama dariw
komit ini untuk menunjuk keHEAD
komit, dan orang tua kedua untuk menunjuk ke komiti
. Terakhir, setstash
untuk menunjuk kew
komit ini :Jika Anda menambahkan
--include-untracked
atau--all
, Git membuat komit ekstrau
,, di antara pembuatani
danw
. Konten snapshot untuku
adalah file yang tidak terlacak tetapi tidak diabaikan (--include-untracked
), atau file yang tidak terlacak meskipun diabaikan (--all
). Ekstra iniu
berkomitmen memiliki tidak ada orang tua, dan kemudian ketikagit stash
merekw
, ia menetapkanw
's ketiga orang tua untuk iniu
komit, sehingga Anda mendapatkan:Git juga, pada titik ini, menghapus semua file pohon kerja yang berakhir di
u
komit (menggunakangit clean
untuk melakukan itu).Mengembalikan simpanan
Saat Anda pergi untuk memulihkan simpanan, Anda memiliki opsi untuk menggunakan
--index
, atau tidak menggunakannya. Ini memberitahugit stash apply
(atau salah satu perintah yang menggunakan internalapply
, sepertipop
) yang seharusnya menggunakan yangi
berkomitmen untuk mencoba mengubah indeks Anda saat ini. Modifikasi ini dilakukan dengan:(kurang lebih; ada banyak detail kecil yang menghalangi ide dasar di sini).
Jika Anda menghilangkan
--index
,git stash apply
mengabaikani
komit sepenuhnya .Jika simpanan hanya memiliki dua komit,
git stash apply
sekarang dapat menerapkanw
komit. Ini dilakukan dengan memanggilgit merge
2 (tanpa mengizinkannya untuk mengkomit atau memperlakukan hasil sebagai gabungan normal), menggunakan komit asli tempat simpanan dibuat (i
induk pertama, danw
induk pertama) sebagai basis gabungan,w
sebagai--theirs
komit, dan komit (HEAD) Anda saat ini sebagai target penggabungan. Jika penggabungan berhasil, semua akan baik-baik saja — yah, setidaknya menurut Git — dangit stash apply
sukses itu sendiri. Jika Anda dulugit stash pop
menggunakan simpanan, kode sekarang menjatuhkan simpanan. 3 Jika penggabungan gagal, Git menyatakan bahwa penerapan gagal. Jika Anda dulugit stash pop
, kode mempertahankan simpanan dan memberikan status kegagalan yang sama seperti untukgit stash apply
.Tetapi jika Anda memiliki komit ketiga itu — jika ada
u
komit di simpanan yang Anda terapkan — maka segalanya berubah! Tidak ada pilihan untuk berpura-pura bahwau
komit tidak ada. 4 Git bersikeras mengekstrak semua file dari yangu
komit, ke dalam arus kerja-pohon. Ini berarti file harus tidak ada sama sekali, atau memiliki konten yang sama seperti diu
komit.Untuk mewujudkannya, Anda dapat menggunakan
git clean
diri Anda sendiri — tetapi ingat bahwa file yang tidak terlacak (diabaikan atau tidak) tidak memiliki keberadaan lain di dalam repositori Git, jadi pastikan semua file ini dapat dihancurkan! Atau, Anda dapat membuat direktori sementara, dan memindahkan file ke sana untuk diamankan — atau bahkan melakukan yang laingit stash save -u
ataugit stash save -a
, karena itu akan berjalangit clean
untuk Anda. Tapi itu hanya membuat Anda memilikiu
simpanan gaya lain untuk ditangani nanti.1 Ini sebenarnya
refs/stash
. Ini penting jika Anda membuat cabang dengan namastash
: nama lengkap cabang adalahrefs/heads/stash
, jadi tidak ada konflik. Tapi jangan lakukan itu: Git tidak keberatan, tapi Anda akan membingungkan diri sendiri. :-)2 The
git stash
kode benar-benar menggunakangit merge-recursive
langsung di sini. Ini diperlukan karena berbagai alasan, dan juga memiliki efek samping untuk memastikan Git tidak memperlakukannya sebagai gabungan saat Anda menyelesaikan konflik dan melakukan.3 Inilah mengapa saya merekomendasikan menghindari
git stash pop
, demigit stash apply
. Anda mendapat kesempatan untuk meninjau apa yang telah diterapkan, dan memutuskan apakah itu benar - benar diterapkan dengan benar. Jika tidak, Anda masih memiliki simpanan yang berarti dapat Anda gunakangit stash branch
untuk memulihkan semuanya dengan sempurna. Nah, dengan asumsi kurangnyau
komitmen sial itu .4 Benar-benar harus ada:
git stash apply --skip-untracked
atau sesuatu. Juga harus ada varian yang berarti letakkan semuau
file komit itu ke direktori baru , misalnyagit stash apply --untracked-into <dir>
, mungkin.sumber
--index
:git stash apply --index
?git stash save --all
, lalu saya langsung melakukannyagit stash apply
, tetapi beberapa file hilang karena saya mengganti namanya dan kemudian membuat lagi (sebelum disimpan). Yang membantu adalah:git checkout stash@{0} -- .
Saya bahkan tidak akan repot-repotgit checkout stash^3 -- .
karena semua tampaknya baik-baik saja sekarang. Sayang sekali saya tidak punya waktu untuk benar-benar memahami apa yang sedang terjadi. Terima kasih.Saya berhasil membuat ulang masalah Anda. Tampaknya jika Anda menyimpan file yang tidak terlacak lalu Anda membuat file tersebut (dalam contoh Anda,
foo.txt
danbar.txt
), maka Anda memiliki perubahan lokal pada file yang tidak terlacak yang akan ditimpa saat Anda melamargit stash pop
.Untuk mengatasi masalah ini, Anda dapat menggunakan perintah berikut. Ini akan menimpa semua perubahan lokal yang belum disimpan jadi hati-hati.
Berikut adalah beberapa informasi lebih lanjut yang saya temukan pada perintah sebelumnya .
sumber
--all
/-a
akan menyertakan file yang diabaikan , jadi mungkin relevan.git merge --squash --strategy-option=theirs stash
pendekatannya lebih baik dalam kasus ini).already exists, no checkout
), periksa jawaban saya di bawah.Untuk memperluas jawaban Daniel Smith : kode itu hanya memulihkan file yang dilacak , meskipun Anda menggunakan
--include-untracked
(atau-u
) saat membuat simpanan. Kode lengkap yang dibutuhkan adalah:git checkout stash -- . git checkout stash^3 -- . git stash drop # Optional to unstage the changes (auto-staged by default). git reset
Ini sepenuhnya memulihkan konten yang dilacak (dalam
stash
) dan konten yang tidak terlacak (dalamstash^3
), lalu menghapus simpanan. Beberapa catatan:git checkout
menyebabkan semuanya menjadi bertahap secara otomatis, jadi saya telah menambahkangit reset
ke semua unstage.stash@{0}
danstash@{0}^3
, dalam pengujian saya, cara kerjanya sama dengan atau tanpa@{0}
Sumber:
stash^3
komit ajaib )sumber
Selain jawaban lain, saya melakukan sedikit trik
git stash apply
(dapat menggunakan perintah apa saja, misalnya terapkan, pop, dll.)sumber