Çalışma ağacımdaki değişiklikleri kaydetmek ve geri yüklemek için sık sık git stash
ve git stash pop
kullanıyorum. Dün çalışma ağacımda sakladığım ve patlattığım bazı değişiklikler vardı ve sonra çalışma ağacımda daha fazla değişiklik yaptım. Geri dönüp dünkü değişiklikleri gözden geçirmek istiyorum, ancak git stash pop
ilgili commit`e yapılan tüm referansları kaldırıyor gibi görünüyor.
Eğer git stash
kullanırsam .git/refs/stash dosyasının stash dosyasını oluşturmak için kullanılan commit referansını içerdiğini biliyorum. Ve .git/logs/refs/stash tüm zulayı içerir*. Ancak bu referanslar git stash pop
tan sonra kayboluyor. Commit'in hala depomda bir yerde olduğunu biliyorum, ancak ne olduğunu bilmiyorum.
Dünkü stash commit referansını kurtarmanın kolay bir yolu var mı?
Bunun bugün benim için kritik olmadığını unutmayın çünkü günlük yedeklerim var ve değişikliklerimi almak için dünkü çalışma ağacına geri dönebilirim. Soruyorum çünkü daha kolay bir yolu olmalı!
Düşürdüğünüz zula taahhüdünün hash'ini öğrendikten sonra, bunu bir zula olarak uygulayabilirsiniz:
git stash apply $stash_hash
Veya bunun için ayrı bir şube oluşturabilirsiniz
git branch recovered $stash_hash
Bundan sonra, tüm normal aletlerle istediğinizi yapabilirsiniz. İşiniz bittiğinde, dalı uçurup atın.
Eğer sadece patlattıysanız ve terminal hala açıksa, ekranda git stash pop
tarafından yazdırılan hash değerine sahip olursunuz]1 (teşekkürler, Dolda).
Aksi takdirde, Linux, Unix için bunu veya Windows için Git Bash'i kullanarak bulabilirsiniz:
git fsck --no-reflog | awk '/dangling commit/ {print $3}'
...veya Windows için Powershell kullanarak:
git fsck --no-reflog | select-string 'dangling commit' | foreach { $bits = $_ -split ' '; echo $bits[2];}
Bu size commit grafiğinizin uçlarında artık herhangi bir dal veya etiketten referans alınmayan tüm commitleri gösterecektir - şimdiye kadar oluşturduğunuz her stash commit de dahil olmak üzere her kayıp commit bu grafikte bir yerde olacaktır.
İstediğiniz stash commitini bulmanın en kolay yolu muhtemelen bu listeyi gitk
e iletmektir:
gitk --all $( git fsck --no-reflog | awk '/dangling commit/ {print $3}' )
...veya Windows için Powershell kullanıyorsanız emragins'in yanıtına bakın.
Bu, erişilebilir olup olmadığına bakılmaksızın, depodaki her bir commit'i gösteren bir depo tarayıcısı başlatacaktır.
Ayrı bir GUI uygulaması yerine konsolda güzel bir grafik tercih ediyorsanız gitk
yerine git log --graph --oneline --decorate
gibi bir şey kullanabilirsiniz.
Zula taahhütlerini tespit etmek için bu formdaki taahhüt mesajlarını arayın:
WIP on somebranch: commithash Bazı eski commit mesajları
Not: Eğer git stash
yaptığınızda bir mesaj vermediyseniz, commit mesajı sadece bu şekilde ("WIP on" ile başlayan) olacaktır.
Az önce kayıp zula taahhüdümü bulmama yardımcı olan bir komut oluşturdum:
for ref in `find .git/objects | sed -e 's#.git/objects/##' | grep / | tr -d /`; do if [ `git cat-file -t $ref` = "commit" ]; then git show --summary $ref; fi; done | less
Bu, .git/objects ağacındaki tüm nesneleri listeler, commit türünde olanları bulur ve ardından her birinin bir özetini gösterir. Bu noktadan sonra, uygun bir "WIP on work" bulmak için commit'lere bakmak yeterli olacaktır: 6a9bb2" ("work" benim dalım, 619bb2 yeni bir commit).
Eğer "git stash pop" yerine "git stash apply" kullansaydım bu sorunu yaşamayacaktım ve "git stash save message" kullansaydım commit'i bulmak daha kolay olabilirdi.
Güncelleme: Nathan'ın fikriyle bu daha kısa olacak:
for ref in `git fsck --unreachable | grep commit | cut -d' ' -f3`; do git show --summary $ref; done | less
git fsck --unreachable | grep commitsha1'i göstermelidir, ancak döndürdüğü liste oldukça büyük olabilir.
git show
git cherry-pick -m 1