Bagaimana `git pull` memakan pekerjaan rumah saya?

53

Saya merasa seperti anak kecil di kantor kepala sekolah yang menjelaskan bahwa anjing itu memakan pekerjaan rumah saya pada malam sebelum waktunya, tetapi saya memandangi beberapa bug kehilangan data gila di wajah dan saya tidak tahu bagaimana hal itu terjadi. Saya ingin tahu bagaimana git bisa memakan seluruh repositori saya! Saya telah memasukkan git melalui alat pemeras berkali-kali dan tidak pernah berkedip. Saya telah menggunakannya untuk membagi repo Subversion 20 Gig menjadi repo 27 git dan menyaring foo keluar dari mereka untuk mengurai kekacauan dan tidak pernah kehilangan satu byte pada saya. Reflog selalu ada untuk digunakan kembali. Kali ini karpetnya hilang!

Dari sudut pandang saya, yang saya lakukan hanyalah menjalankan git pulldan menghapus seluruh repositori lokal saya. Saya tidak bermaksud itu "mengacaukan versi check out" atau "cabang tempat saya berada" atau semacamnya. Maksudku semuanya hilang .

Berikut adalah cuplikan layar terminal saya saat kejadian:

tangkapan layar insiden

Biarkan saya memandu Anda melalui itu. Command prompt saya menyertakan data tentang repo git saat ini (menggunakan implementasi vcs_info prezto) sehingga Anda dapat melihat kapan repo git menghilang. Perintah pertama cukup normal:

  » caleb » jaguar » ~/p/w/incil.info » ◼  zend ★ »
❯❯❯ git co master
Switched to branch 'master'
Your branch is up-to-date with 'origin/master'.

Di sana Anda dapat melihat saya berada di cabang 'zend', dan memeriksa master. Sejauh ini bagus. Anda akan melihat pada prompt sebelum perintah saya berikutnya bahwa ia berhasil mengganti cabang:

  » caleb » jaguar » ~/p/w/incil.info » ◼  master ★ »
❯❯❯ git pull
remote: Counting objects: 37, done.
remote: Compressing objects: 100% (37/37), done.
remote: Total 37 (delta 25), reused 0 (delta 0)
Unpacking objects: 100% (37/37), done.
From gitlab.alerque.com:ipk/incil.info
 + 7412a21...eca4d26 master     -> origin/master  (forced update)
   f03fa5d..c8ea00b  devel      -> origin/devel
 + 2af282c...009b8ec verse-spinner -> origin/verse-spinner  (forced update)
First, rewinding head to replay your work on top of it...
>>> elapsed time 11s

Dan begitu saja itu hilang. Marker waktu yang telah berlalu menampilkan sebelum prompt berikutnya jika lebih dari 10 detik telah berlalu. Git tidak memberikan output apa pun di luar pemberitahuan bahwa ia memutar ulang untuk diputar ulang. Tidak ada indikasi bahwa itu selesai.

Prompt berikutnya tidak menyertakan data tentang cabang apa yang kita gunakan atau status git.

Tidak menyadari bahwa itu telah gagal, saya dengan tidak sengaja mencoba menjalankan perintah git yang lain hanya untuk diberi tahu bahwa saya tidak berada dalam git repo. Perhatikan PWD tidak berubah:

  » caleb » jaguar » ~/p/w/incil.info »
❯❯❯ git fetch --all
fatal: Not a git repository (or any parent up to mount point /home)
Stopping at filesystem boundary (GIT_DISCOVERY_ACROSS_FILESYSTEM not set).

Setelah ini melihat-lihat menunjukkan bahwa saya berada di direktori yang benar-benar kosong. Tidak ada. Tidak ada direktori '.git', tidak ada. Kosong.

Git lokal saya ada di versi 2.0.2. Berikut adalah beberapa berita dari konfigurasi git saya yang mungkin relevan untuk mengetahui apa yang terjadi:

[branch]
        autosetuprebase = always
        rebase = preserve
[pull]
        rebase = true
[rebase]
        autosquash = true
        autostash = true
[alias]
        co = checkout

Sebagai contoh saya telah git pullmenetapkan untuk selalu melakukan rebase bukan penggabungan, sehingga bagian dari output di atas normal.

Saya dapat memulihkan data. Saya tidak berpikir ada objek git selain beberapa simpanan tidak penting yang belum didorong ke repo lain, tapi saya ingin tahu apa yang terjadi .

Saya telah memeriksa untuk:

  • Pesan di dmesg atau jurnal systemd. Tidak ada yang bahkan relevan.
  • Tidak ada indikasi kegagalan drive atau sistem file (LVM + LUKS + EXT4 semuanya terlihat normal). Tidak ada yang hilang + ditemukan.
  • Saya tidak menjalankan apa pun. Tidak ada dalam sejarah saya tidak menunjukkan di atas, dan tidak ada terminal lain yang digunakan selama waktu ini. Tidak ada rmperintah yang beredar yang mungkin telah dieksekusi di CWD yang salah, dll.
  • Mengolok-olok repo git lain di direktori lain tidak menunjukkan kelainan nyata git pulls.

Apa lagi yang harus saya cari di sini?

Caleb
sumber
4
@ Patrick Seperti yang saya jelaskan di pertanyaan, .gittidak tidak ada. Tidak ada yang berhasil — apa yang dulunya adalah direktori git root tidak memiliki apa-apa di dalamnya.
Caleb
2
@Alexander Operasi tarikan adalah normal (selain menjadi rebase bukan gabungan). Pemberitahuan tentang pembaruan yang dipaksakan menunjukkan bahwa repo yang saya tarik memiliki gaya dorong yang mengatur ulang dari posisi yang berbeda dari repo lokal terakhir melihatnya di. Ini normal karena saya menyinkronkan materi yang dikembangkan secara aktif dan sering dirubah ulang di antara komputer saya sendiri, bukan cabang publik yang akan dilihat oleh pengembang lain.
Caleb
3
@Caleb prompt shell Anda menyertakan indikasi git branch, yang berarti membentuk PS1 termasuk perintah git yang tidak diekspos di log Anda. Mereka pada dasarnya dapat mengubah gambar dan bisa menjadi sumber masalah. Anda harus memperbarui pertanyaan yang menjelaskan dengan tepat bagaimana shell prompt Anda dibentuk, perintah apa yang dijalankan untuk mendapatkan cabang saat ini, dan mempertimbangkan kembali bagaimana mereka dapat merusak repo Anda.
Netch
2
@ Caleb Anda harus benar-benar bertanya di milis git development; Anda bisa menulisnya sebagai laporan bug, atau hanya bertanya secara informal - itu sama saja. Ada beberapa pengembang yang mengenal git dengan sangat baik - mereka mungkin dapat mengetahui dengan intuisi apa yang bisa terjadi. (Jika tidak, mereka hanya akan mengikuti diskusi dengan tenang.) Dan mereka tahu apakah itu bahagia sebelumnya. (Melaporkan ada cara "resmi" untuk melaporkan bug untuk git)
Volker Siegel
7
@Wildcard Sebenarnya saya bermaksud mengumpulkan jawaban untuk ini karena saya benar-benar mengetahui apa yang terjadi. Sistem baru-baru ini muncul dari tidur dan jaringan telah keluar selama berhari-hari sebelum tidur. Di suatu tempat dalam proses itu saya meninggalkan proses pacman berjalan yang mencoba untuk mengupgrade sesuatu pada sistem. Singkatnya, glibc diperbarui dan biner git ditimpa. Karena cara garpu itu sendiri, satu contoh akhirnya menjadi berbeda dari yang lain dan mereka makan siang satu sama lain. Direktori itu benar-benar kosong (bukan hanya appar
Caleb

Jawaban:

6

Ya, gitmakan pekerjaan rumah saya. Semua itu.

Saya membuat ddgambar disk ini setelah kejadian dan mengacaukannya nanti. Merekonstruksi serangkaian acara dari log sistem, saya menyimpulkan apa yang terjadi adalah sesuatu seperti ini:

  1. Perintah pembaruan sistem ( pacman -Syu) telah dikeluarkan beberapa hari sebelum kejadian ini.
  2. Penghentian jaringan yang diperpanjang berarti dibiarkan mencoba mengunduh paket. Frustrasi karena kurangnya internet, saya menempatkan sistem untuk tidur dan pergi tidur.
  3. Beberapa hari kemudian sistem dibangunkan dan mulai menemukan dan mengunduh paket lagi.
  4. Pengunduhan paket selesai kadang-kadang sebelum saya kebetulan bermain-main dengan repositori ini.
  5. Instalasi sistem glibc mendapat pembaruan setelah git checkoutdan sebelum git pull.
  6. The gitbiner harus digantikan setelah git pulldimulai dan sebelum selesai.
  7. Dan pada hari ketujuh, gitberistirahat dari semua pekerjaannya. Dan menghapus dunia sehingga semua orang harus beristirahat juga.

Saya tidak tahu persis kondisi ras apa yang menyebabkan ini terjadi, tetapi menukar binari di tengah operasi tentu saja tidak baik atau kondisi yang dapat diuji / diulang. Biasanya salinan biner yang berjalan disimpan dalam memori, tetapi gitaneh dan sesuatu tentang cara itu menumbuhkan kembali versi itu sendiri, saya yakin menyebabkan kekacauan ini. Jelas itu seharusnya mati daripada menghancurkan segalanya, tapi itulah yang terjadi.

Caleb
sumber
1
git bisa gagal karena git dibuat menggunakan perintah differend, bukan biner tunggal. Sebuah tarikan git sederhana dieksekusi git-fetch, git-rebaseatau git-mergedangit gc
Ferrybig
2

Mungkin dengan gagal mendefinisikan path file yang akan dihapus.

Kasing Anda mengingatkan saya pada hari yang indah bahwa ketika remove(path)metode buatan saya mencoba menghapus folder root karena parameter yang diberikan adalah string kosong yang dikoreksi oleh OS (!) Sebagai folder root.

Ini mungkin bug git yang serupa. Seperti yang:

  1. Perintah rebase ingin menghapus file seperti remove(project_folder + file_path)(kode semu)
  2. Entah bagaimana, saat file_pathitu kosong.
  3. Perintah dievaluasi sebagai beberapa hal seperti remove(project_folder)
maliaya
sumber
1

Dengan sedikit keberuntungan, Anda dapat memperbaikinya dengan perintah berikut:

git reset --hard ORIG_HEAD  

Ketika potensi perubahan berbahaya dimulai, git menyembunyikan status Anda saat ini di ORIG_HEAD. Dengan itu Anda dapat membatalkan gabungan atau rebase.

Manual Git: Membatalkan Penggabungan

Routhinator
sumber
4
Saya tidak berpikir Anda membaca seluruh pertanyaan. Perbaikan semacam ini benar-benar keluar dari pertanyaan karena tidak ada meta-data git . Melakukan reset seperti ini membutuhkan direktori .git yang masih ada dan beberapa objek di dalamnya berfungsi. Saya tidak memiliki apa apa. Ini bukan hanya direktori kerja yang kacau, itu bukan lagi repositori dalam bentuk apa pun.
Caleb
Ahh, permintaan maaf saya. Itu sangat tidak biasa. Jika git repo hilang, saya kira tidak akan ada cara untuk memulihkan kecuali Anda membayangi file di linux dan memiliki cadangan fs file. Saya akan menghapus jawaban saya karena tidak relevan.
Routhinator
Ya saya tahu ini masalah yang tidak biasa (dan saya punya cadangan). Pertanyaan saya di sini adalah bagaimana kesalahannya ... di mana mencari bug di git atau driver sistem file saya atau apa pun yang bisa dicuri untuk memakan direktori di tengah operasi seperti ini.
Caleb
Saya juga sangat penasaran. Akankah hal seperti ini terjadi pada repo saya.
Routhinator
-1

Sepertinya seseorang menjalankan git push --forcerepo ini, dan Anda menarik perubahan itu. Coba kloning repo segar, yang seharusnya membuat Anda kembali ke kondisi kerja bersih lagi.

Conorsch
sumber
1
Dorongan paksa mengubah beberapa komitmen terakhir. Bukan itu yang saya tarik (direktori kerja tidak lagi direktori kerja!) Dan bahkan jika itu kloning ulang tidak masuk akal.
Caleb
4
Saya tidak berpikir Anda dapat menghapus .gitdirektori someones dengan dorongan paksa
Grzegorz