Bagaimana cara memulihkan dari master asal git push -f yang salah?

93

Saya baru saja melakukan sumber yang salah ke proyek saya menggunakan --forceopsi.

Apakah mungkin untuk kembali? Saya memahami bahwa semua cabang sebelumnya telah ditimpa menggunakan -fopsi, jadi saya mungkin telah mengacaukan revisi saya sebelumnya.

David van Dugteren
sumber
kemungkinan duplikat dari Apakah ada cara untuk membatalkan git push -f?
cmbuckley

Jawaban:

55

Git umumnya tidak membuang apa pun, tetapi memulihkan dari ini mungkin masih sulit.

Jika Anda memiliki sumber yang benar maka Anda bisa mendorongnya ke remote dengan --forceopsi. Git tidak akan menghapus cabang apa pun kecuali Anda menyuruhnya. Jika Anda benar-benar kehilangan komit, lihat panduan berguna ini untuk memulihkan komit . Jika Anda mengetahui SHA-1 dari komit yang Anda inginkan, Anda mungkin baik-baik saja.

Hal terbaik untuk dilakukan: Cadangkan semuanya dan lihat apa yang masih ada di repositori lokal Anda. Lakukan hal yang sama pada remote jika memungkinkan. Gunakan git fsckuntuk melihat apakah Anda dapat memulihkan sesuatu, dan yang terpenting JANGAN dijalankangit gc .

Di atas segalanya, jangan pernah menggunakan --forceopsi kecuali Anda benar-benar bersungguh-sungguh.

Cameron Skinner
sumber
65
Anda dapat dengan mudah melihat reflog untuk menentukan di mana cabang-cabang jarak jauh awalnya berada. Misalnya git reflog show remotes/origin/master,. Anda harus bisa melihat dorongan Anda di sana; komit di baris sebelumnya adalah tempat sebelum Anda mengacaukannya. Anda kemudian dapat mendorong revisi itu (dengan --force) ke asal, dan kembali ke tempat Anda sebelumnya!
Kaskabel
@David: Oh. Anda tidak menyebutkan dalam pertanyaan Anda bahwa Anda tidak memiliki repo. (Ini tentu saja sesuatu yang tidak ingin Anda lakukan.) Namun, jika Anda memiliki akses sistem file di mana Anda didorong, Anda masih dapat melakukan semua ini di sana.
Kaskabel
1
@David: Astaga. Selalu baik untuk memiliki direktori Anda saat ini sebagai bagian dari prompt Anda untuk menghindari hal semacam itu.
Kaskabel
1
@Jefromi Saya pikir apa yang Anda katakan ada jawaban yang sebenarnya: Bahkan dengan versi lama (tidak git fetchdiedit untuk waktu yang lama) Anda dapat menampilkan reflog dari sisi GitHub dan memulihkan!
nh2
1
Dimana jawaban dari @Jefromi ini? Saya tidak melihat pengguna tersebut disebutkan di halaman ini di luar utas komentar ini.
Don McCurdy
47

Jika Anda mengetahui hash komit, itu mudah, cukup buat ulang cabang Anda.

5794458...b459f069 master -> master (forced update)

Hapus cabang jarak jauh:

git push origin :master

kemudian buat ulang cabang Anda dengan perintah berikut:

git checkout 5794458
git branch master
git push origin master
pengguna1094125
sumber
28

Solusinya sudah disebutkan di sini

# work on local master
git checkout master

# reset to the previous state of origin/master, as recorded by reflog
git reset --hard origin/master@{1}

# at this point verify that this is indeed the desired commit.
# (if necessary, use git reflog to find the right one, and
# git reset --hard to that one)

# finally, push the master branch (and only the master branch) to the server
git push -f origin master
Abdelhafid
sumber
Terima kasih, ini berhasil untuk saya. Saya tidak memiliki akses untuk menghapus master sehingga komentar yang disetujui gagal.
Andi
Ya, dan git reflog show remotes/origin/masterjika git reflog diperlukan (seperti yang disebutkan oleh @Cascabel di atas)
Josiah Yoder
2
Ini adalah jawaban yang benar, terima kasih telah menautkan ke jawaban yang benar.
Noitidart
6

Jika Anda tidak berada di repo lokal tempat dorongan paksa berasal, pada tingkat asal / master tidak ada cara untuk memulihkan. Tetapi jika Anda cukup beruntung untuk menggunakan GitHub atau GitHub for Enterprise , Anda dapat melihat ke REST API dan mengambil komit yang hilang sebagai tambalan, contoh:

  1. Buat daftar acara dan temukan format panjang komit sha1

https://api.github.com/repos/apache/logging-log4j2/events

  1. Unduh komit yang hilang dan ambil tambalan terkait di jalur json .files [] / patch

https://api.github.com/repos/apache/logging-log4j2/commits/889232e28f3863d2a17392c06c1dd8cac68485de

  1. Terapkan secara lokal dan dorong lagi

git apply patch.patch && git commit -m "restore commit" && git push origin master

Pierrick HYMBERT
sumber
4

Cara lain untuk memulihkan komit yang hilang atau bahkan untuk mencari tahu komit apa yang hilang, jika dorongan sebelumnya tidak berasal dari repo lokal Anda, adalah dengan melihat mesin CI Anda.

Jika Anda memiliki pekerjaan yang menguji cabang master setelah setiap komit (atau serangkaian komit berurutan), yang seharusnya Anda miliki, Anda dapat melihat apa yang terakhir kali diuji. Itu adalah komitmen yang perlu Anda pulihkan.

Mesin CI bahkan dapat menyimpan tiruan lokal dari repo, yang darinya Anda mungkin dapat melakukan pemulihan ini.

Sumber: mungkin Pengiriman Berkelanjutan: Rilis Perangkat Lunak yang Andal melalui Build, Test, dan Deployment Automation (Addison-Wesley Signature Series (Fowler))

pengguna7610
sumber
3

Ya, Anda dapat memulihkan komit setelahnya git push -f your_branch

Teks dari Dokumen :

Pangkas entri yang lebih lama dari waktu yang ditentukan. Jika opsi ini tidak ditentukan, waktu kedaluwarsa diambil dari pengaturan konfigurasi gc.reflogExpire, yang secara default ditetapkan ke 90 hari. --expire = semua entri plum terlepas dari usianya; --expire = tidak pernah mematikan pemangkasan entri yang dapat dijangkau (tetapi lihat --expire-unreachable).

Jadi Anda bisa melakukan:

1- git reflog

masukkan deskripsi gambar di sini

2- Anda memilih Head_Number yang ingin Anda pulihkan git reset –hard HEAD@{HEAD-NUMBER}

masukkan deskripsi gambar di sini

3- Anda dapat melihat semua komitmen di kepala ini dengan git cherry -v branch_name

4- pada akhirnya Anda harus memaksa mendorong git push -f branch_name

ATAU

1- Dapatkan nomor SHA dari klien GIT Anda (antarmuka)

git reset --hard commit_SHA

2- paksa dorong

git push -f your_branch

Semoga ini membantu

Yakub
sumber
2

Saya melakukan hal yang sama saat membatalkan dorongan terakhir hanya untuk satu file. Akhirnya akan kembali ke keadaan asli repositori. Saya menggunakan perintah git dari Linus karena saya memiliki salinan lokalnya di Linux. Untungnya salinan itu masih utuh.

Yang saya lakukan adalah (setelah dengan panik membuat beberapa salinan repo lokal):

git add .
git status

(dikatakan bahwa origin / master berada di depan dengan 68 komit, baiklah ... itu semua adalah komit yang saya hapus)

git remote set-url origin <GIT_SSH_URL>
git push

Dan semuanya dipulihkan seperti sebelum saya melakukan dorongan kuat. Hal terpenting untuk diingat adalah jangan pernah melakukan git checkout. setelah Anda mendorong dengan paksa. Tetapi praktik terbaik adalah menonaktifkan opsi push. Saya tidak pernah menggunakannya lagi. Mempelajari pelajaran saya !!

Pran
sumber
1

Untuk orang-orang yang berada dalam situasi yang sangat buruk seperti saya sebelumnya (misalnya, jika Anda mendapatkan bad objectkesalahan saat berlari git reset --hard):

Saya menulis skrip yang disebut penghemat pohon yang menarik semua file Anda dari GitHub API sebagai upaya terakhir. Berikut cara menggunakannya:

  1. Gandakan treesaverskrip dan cduntuk itu.
  2. Temukan SHAstring pohon yang ingin Anda pulihkan dengan mengakses https://api.github.com/repos/<your_username_or_org>/<repo>/events.
  3. Di payloadproperti yang sesuai dengan peristiwa push Anda, temukan yang commitingin Anda kembalikan dan klik url.
  4. Di bawah commit.tree, salin tree's url.
  5. Lari python3 main.py <tree_url> <path_to_save_to>.

Misalnya, dalam kasus saya, saya akan menjalankan:

python3 main.py https://api.github.com/repos/anthonykrivonos/my-repo/git/trees/1234567 .

Tentu saja, PR menyambut.

Anthony Krivonos
sumber
0

Di sini Anda dapat membaca keputusan https://evilmartians.com/chronicles/git-push---force-and-how-to-deal-with-it

Yang kedua membantu saya. Saya melakukan kesalahan perintah ini

1) (some-branch) git pull -> correct command was git pull origin some-branch

2) (some-branch) git push -f origin some-branch

Setelah perintah ini saya kehilangan tiga komit. Untuk memulihkannya, saya melihat ke terminal tempat saya melakukan 'git pull' yang salah dan telah melihat keluaran seperti

60223bf ... 0b258eb some-branch -> origin / some-branch

Hash 0b258eb kedua persis seperti yang saya butuhkan. Jadi, saya mengambil hash ini dan menghasilkan perintah

git push --force origin 0b258eb:some-branch
Andrey
sumber