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, dan w
untuk konten work-tree. Ingat juga bahwa setiap komit menyimpan sebuah snapshot. Dalam komit normal, snapshot ini dibuat dari konten index / staging-area. Jadi i
komit sebenarnya adalah komit normal sempurna! Hanya saja tidak di cabang mana pun:
...--o--o--o <-- branch (HEAD)
|
i
Jika Anda membuat simpanan normal, git stash
kodenya w
sekarang dengan menyalin semua file pohon kerja terlacak Anda (ke dalam indeks tambahan sementara). Git menetapkan orang tua pertama dari w
komit ini untuk menunjuk ke HEAD
komit, dan orang tua kedua untuk menunjuk ke komit i
. Terakhir, set stash
untuk menunjuk ke w
komit ini :
...--o--o--o <-- branch (HEAD)
|\
i-w <-- stash
Jika Anda menambahkan --include-untracked
atau --all
, Git membuat komit ekstra u
,, di antara pembuatan i
dan w
. Konten snapshot untuk u
adalah file yang tidak terlacak tetapi tidak diabaikan ( --include-untracked
), atau file yang tidak terlacak meskipun diabaikan ( --all
). Ekstra ini u
berkomitmen memiliki tidak ada orang tua, dan kemudian ketika git stash
merek w
, ia menetapkan w
's ketiga orang tua untuk ini u
komit, sehingga Anda mendapatkan:
...--o--o--o <-- branch (HEAD)
|\
i-w <-- stash
/
u
Git juga, pada titik ini, menghapus semua file pohon kerja yang berakhir di u
komit (menggunakan git clean
untuk melakukan itu).
Mengembalikan simpanan
Saat Anda pergi untuk memulihkan simpanan, Anda memiliki opsi untuk menggunakan --index
, atau tidak menggunakannya. Ini memberitahu git stash apply
(atau salah satu perintah yang menggunakan internal apply
, seperti pop
) yang seharusnya menggunakan yang i
berkomitmen untuk mencoba mengubah indeks Anda saat ini. Modifikasi ini dilakukan dengan:
git diff <hash-of-i> <hash-of-i's-parent> | git apply --index
(kurang lebih; ada banyak detail kecil yang menghalangi ide dasar di sini).
Jika Anda menghilangkan --index
, git stash apply
mengabaikan i
komit sepenuhnya .
Jika simpanan hanya memiliki dua komit, git stash apply
sekarang dapat menerapkan w
komit. Ini dilakukan dengan memanggil git merge
2 (tanpa mengizinkannya untuk mengkomit atau memperlakukan hasil sebagai gabungan normal), menggunakan komit asli tempat simpanan dibuat ( i
induk pertama, dan w
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 — dan git stash apply
sukses itu sendiri. Jika Anda dulu git 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 untuk git 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 bahwa u
komit tidak ada. 4 Git bersikeras mengekstrak semua file dari yang u
komit, ke dalam arus kerja-pohon. Ini berarti file harus tidak ada sama sekali, atau memiliki konten yang sama seperti di u
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 lain git stash save -u
atau git stash save -a
, karena itu akan berjalan git clean
untuk Anda. Tapi itu hanya membuat Anda memiliki u
simpanan gaya lain untuk ditangani nanti.
1 Ini sebenarnya refs/stash
. Ini penting jika Anda membuat cabang dengan nama stash
: nama lengkap cabang adalah refs/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 menggunakan git 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
, demi git 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 gunakan git stash branch
untuk memulihkan semuanya dengan sempurna. Nah, dengan asumsi kurangnya u
komitmen sial itu .
4 Benar-benar harus ada: git stash apply --skip-untracked
atau sesuatu. Juga harus ada varian yang berarti letakkan semua u
file komit itu ke direktori baru , misalnya git stash apply --untracked-into <dir>
, mungkin.
git stash show -p | git apply --3