Saya mencoba memulihkan pekerjaan saya. Aku dengan bodohnya melakukannya git reset --hard
, tapi sebelumnya aku hanya get add .
melakukan dan tidak melakukannya git commit
. Tolong bantu! Ini log saya:
MacBookPro:api user$ git status
# On branch master
# Changes to be committed:
# (use "git reset HEAD <file>..." to unstage)
# modified: .gitignore
...
MacBookPro:api user$ git reset --hard
HEAD is now at ff546fa added new strucuture for api
Apakah mungkin untuk membatalkan git reset --hard
dalam situasi ini?
Jawaban:
Anda harus dapat memulihkan file apa pun yang Anda tambahkan ke indeks (misalnya, seperti dalam situasi Anda, dengan
git add .
) meskipun ini mungkin sedikit berhasil. Untuk menambahkan file ke indeks, git menambahkannya ke database objek, yang berarti file tersebut dapat dipulihkan selama pengumpulan sampah belum terjadi. Ada contoh bagaimana melakukan ini diberikan dalam jawaban Jakub Narębski di sini:Namun, saya mencobanya pada repositori percobaan, dan ada beberapa masalah -
--cached
seharusnya--cache
, dan saya menemukan bahwa itu tidak benar-benar membuat.git/lost-found
direktori. Namun, langkah-langkah berikut berhasil untuk saya:Itu harus mengeluarkan semua objek dalam database objek yang tidak dapat dijangkau oleh referensi mana pun, dalam indeks, atau melalui reflog. Outputnya akan terlihat seperti ini:
... dan untuk setiap gumpalan tersebut, Anda dapat melakukan:
Untuk mengeluarkan isi file.
Output terlalu banyak?
Update dalam menanggapi sehe 's komentar di bawah ini:
Jika Anda menemukan bahwa Anda memiliki banyak komit dan struktur yang terdaftar dalam output dari perintah itu, Anda mungkin ingin menghapus dari output objek apapun yang direferensikan dari komit yang tidak direferensikan. (Biasanya Anda dapat kembali ke komit ini melalui reflog - kami hanya tertarik pada objek yang telah ditambahkan ke indeks tetapi tidak pernah dapat ditemukan melalui komit.)
Pertama, simpan output dari perintah tersebut, dengan:
Sekarang nama objek dari komit yang tidak dapat dijangkau itu dapat ditemukan dengan:
Jadi Anda bisa menemukan pohon dan objek yang telah ditambahkan ke indeks, tetapi tidak dikomit pada titik mana pun, dengan:
Itu sangat mengurangi jumlah objek yang harus Anda pertimbangkan.
Pembaruan: Philip Oakley di bawah ini menyarankan cara lain untuk mengurangi jumlah objek yang perlu dipertimbangkan, yaitu dengan hanya mempertimbangkan file yang paling baru diubah di bawah
.git/objects
. Anda dapat menemukannya dengan:(Saya menemukan
find
doa itu di sini .) Akhir dari daftar itu mungkin terlihat seperti:Dalam hal ini Anda dapat melihat objek tersebut dengan:
(Perhatikan bahwa Anda harus menghapus
/
di ujung jalur untuk mendapatkan nama objek.)sumber
Saya baru saja melakukan
git reset --hard
dan kehilangan satu komit. Tapi saya tahu hash komit, jadi saya bisa melakukannyagit cherry-pick COMMIT_HASH
untuk memulihkannya.Saya melakukan ini dalam beberapa menit setelah kehilangan commit, jadi mungkin berhasil untuk sebagian dari Anda.
sumber
git reflog
, misalnyagit reset --hard
->git reflog
( lihat hash HEAD @ {1}) dan terakhirgit cherry-pick COMMIT_HASH
git reset --hard
( dengan asumsi Anda belum melakukan apa pun setelah perintah itu) adalahgit reset --hard @{1}
Berkat Mark Longair, saya mendapatkan barang-barang saya kembali!
Pertama saya menyimpan semua hash ke dalam file:
selanjutnya saya meletakkan semuanya (menghapus hal 'gumpalan yang tidak dapat dijangkau') dalam daftar dan memasukkan semua data ke dalam file baru ... Anda harus memilih file Anda dan mengganti namanya lagi yang Anda butuhkan ... tetapi saya hanya membutuhkan beberapa file..harap ini membantu seseorang ...
sumber
mkdir lost; git fsck --cache --unreachable $(git for-each-ref --format="%(objectname)") | grep -Po '\s\S{40}$' | xargs -i echo "git show {} > lost/{}.blob" | sh
. File akan berakhir dilost/*.blob
Solusi @ Ajedi32 di komentar bekerja untuk saya dalam situasi ini.
Perhatikan bahwa semua solusi ini bergantung pada tidak adanya git gc, dan beberapa di antaranya mungkin menyebabkannya, jadi saya akan mengeposkan konten direktori .git Anda sebelum mencoba apa pun sehingga Anda memiliki snapshot untuk kembali ke jika tidak ada. tidak bekerja untukmu.
sumber
git reset --hard
, yang mengacaukan repo saya dengan cara yang tidak diketahui. @Duncan, apa yang dilakukan @ {1}? dan komentar mana yang Anda maksud? Apakah ini menyetel ulanggit reset
?Mengalami masalah yang sama, tetapi belum menambahkan perubahan ke indeks. Jadi semua perintah di atas tidak mengembalikan perubahan yang saya inginkan.
Setelah semua jawaban rumit di atas, ini adalah petunjuk yang naif, tetapi mungkin itu akan menyelamatkan seseorang yang tidak memikirkannya terlebih dahulu, seperti yang saya lakukan.
Dengan putus asa, saya mencoba menekan CTRL-Z di editor saya (LightTable), sekali di setiap tab yang terbuka - untungnya ini memulihkan file di tab itu, ke status terbaru sebelum
git reset --hard
. HTH.sumber
Ini mungkin jelas bagi para profesional git di luar sana, tetapi saya ingin memasangnya karena dalam pencarian saya yang panik, saya tidak melihat hal ini diangkat.
Saya membuat beberapa file, dan melakukan
git reset --hard
, sedikit panik, dan kemudian menyadari bahwa status saya menunjukkan semua file saya masih dalam stage serta semua penghapusannya tidak diatur.Pada titik ini Anda dapat melakukan perubahan bertahap tersebut, selama Anda tidak melakukan tahap penghapusannya. Setelah ini, Anda hanya perlu mengerahkan keberanian untuk melakukannya
git reset --hard
sekali lagi, yang akan membawa Anda kembali ke perubahan yang telah Anda lakukan dan sekarang baru saja dilakukan.Sekali lagi, ini mungkin bukan hal baru bagi kebanyakan orang, tetapi saya berharap karena ini membantu saya dan saya tidak menemukan apa pun yang menyarankan hal ini, ini dapat membantu orang lain.
sumber
Ya ampun, saya menarik rambut saya sampai saya menemukan pertanyaan ini dan jawabannya. Saya percaya jawaban yang benar dan ringkas untuk pertanyaan yang diajukan hanya tersedia jika Anda menggabungkan dua komentar di atas jadi ini semua ada di satu tempat:
Seperti yang disebutkan oleh chilicuil, jalankan
git reflog
untuk mengidentifikasi di sana hash komit yang ingin Anda buka lagiSeperti yang disebutkan oleh akimsko, Anda mungkin TIDAK ingin memilih ceri kecuali Anda hanya kehilangan satu komit, jadi Anda harus lari
git reset --hard <hash-commit-you-want>
Catatan untuk pengguna egit Eclipse: Saya tidak dapat menemukan cara untuk melakukan langkah-langkah ini dalam Eclipse dengan egit. Menutup Eclipse, menjalankan perintah di atas dari jendela terminal, dan kemudian membuka kembali Eclipse bekerja dengan baik untuk saya.
sumber
Solusi di atas dapat berfungsi, namun, ada cara yang lebih sederhana untuk memulihkannya daripada melalui
git
pembatalan kompleks -s. Saya akan menebak bahwa kebanyakan git-reset terjadi pada sejumlah kecil file, dan jika Anda sudah menggunakan VIM, ini mungkin solusi yang paling hemat waktu. Peringatannya adalah Anda sudah harus menggunakanViM's
persistent-undo, yang harus Anda gunakan dengan cara apa pun, karena ini memberi Anda kemampuan untuk membatalkan perubahan dalam jumlah yang tidak terbatas.Berikut langkah-langkahnya:
Di vim tekan
:
dan ketik perintahset undodir
. Jika Anda telahpersistent undo
mengaktifkan di Anda.vimrc
, itu akan menunjukkan hasil yang mirip denganundodir=~/.vim_runtime/temp_dirs/undodir
.Di repo Anda gunakan
git log
untuk mengetahui tanggal / waktu terakhir Anda membuat komit terakhirDi shell Anda, navigasikan ke
undodir
penggunaan Andacd ~/.vim_runtime/temp_dirs/undodir
.Dalam direktori ini gunakan perintah ini untuk menemukan semua file yang telah Anda ubah sejak komit terakhir
find . -newermt "2018-03-20 11:24:44" \! -newermt "2018-03-23" \( -type f -regextype posix-extended -regex '.*' \) \-not -path "*/env/*" -not -path "*/.git/*"
Di sini "2018-03-20 11:24:44" adalah tanggal dan waktu pengubahan terakhir. Jika tanggal Anda melakukan
git reset --hard
adalah "2018-03-22", gunakan "2018-03-22", lalu gunakan "2018-03-23". Ini karena quirk of find, di mana batas bawah inklusif, dan batas atasnya eksklusif. https://unix.stackexchange.com/a/70404/242983Selanjutnya pergi ke masing-masing file yang membukanya di vim, dan lakukan "20m sebelumnya". Anda dapat menemukan detail lebih lanjut tentang "sebelumnya" dengan menggunakan "h sebelumnya". Di sini
earlier 20m
berarti kembali ke status file 20 menit ke belakang, dengan asumsi Anda melakukangit hard --reset
, 20 menit mundur. Ulangi ini di semua file yang dikeluarkan darifind
perintah. Saya yakin seseorang dapat menulis skrip yang akan menggabungkan hal-hal ini.sumber
Saya menggunakan IntelliJ dan dapat menelusuri setiap file dan melakukan:
Edit -> reload from disk
Untungnya, saya baru saja melakukan yang
git status
benar sebelum menghapus perubahan kerja saya, jadi saya tahu persis apa yang harus saya muat ulang.sumber
Mengingat hierarki file Anda dan menggunakan teknik Mark Longair dengan modifikasi Phil Oakley menghasilkan hasil yang dramatis.
Pada dasarnya jika Anda setidaknya menambahkan file ke repo tetapi tidak melakukannya, Anda dapat memulihkan dengan menggunakan secara interaktif
git show
, memeriksa log, dan menggunakan pengalihan shell untuk membuat setiap file (mengingat jalur yang Anda minati).HTH!
sumber
Jika Anda baru saja meninjau,
git diff
maka ada cara lain untuk memulihkan dari insiden seperti ini, bahkan ketika Anda belum melakukan perubahan: jika keluaran darigit diff
masih dalam buffer konsol Anda, Anda dapat menggulir ke atas, salin-tempel diff ke dalam file dan menggunakanpatch
alat untuk menerapkan diff untuk pohon Anda:patch -p0 < file
. Pendekatan ini menyelamatkan saya beberapa kali.sumber