Menyetel ulang remote ke komit tertentu

709

Saya ingin membuang semua perubahan yang dilakukan setelah komit <commit-hash>. Jadi saya melakukannya:

git reset --hard <commit-hash>

Sekarang saya ingin melakukan hal yang sama dengan remote saya. Bagaimana saya bisa melakukan ini? Saya telah melakukan beberapa komitmen (dan mendorong) setelah <commit-hash>dan saya hanya ingin membuang semuanya. Apakah ada sesuatu yang sangat salah di jalan dan saya tidak ingin membuatnya lebih buruk dari yang sudah ada. ; (

Saya pada dasarnya ingin memundurkan origin/masterke<commit-hash>

nacho4d
sumber
3
Apakah Anda yakin origin/masterbelum ditarik dan didorong oleh pengguna lain? Mengubah riwayat repositori publik (yaitu non-lokal) adalah sesuatu yang ingin Anda hindari setiap saat.
vindia
Kemungkinan duplikat dari Bagaimana cara mengembalikan beberapa komit git?
Michael Freidgeim

Jawaban:

1252

Dengan asumsi bahwa cabang Anda dipanggil di mastersini dan dari jarak jauh, dan bahwa kendali jarak jauh originAnda disebut dapat Anda lakukan:

 git reset --hard <commit-hash>
 git push -f origin master

Namun, Anda harus menghindari melakukan ini jika ada orang lain yang bekerja dengan repositori jarak jauh Anda dan telah menarik perubahan Anda. Dalam hal ini, akan lebih baik untuk mengembalikan komit yang tidak Anda inginkan, kemudian dorong seperti biasa.

Pembaruan: Anda telah menjelaskan di bawah ini bahwa orang lain telah menarik perubahan yang Anda dorong, jadi itu lebih baik untuk membuat komit baru yang mengembalikan semua perubahan itu . Ada penjelasan yang bagus tentang pilihan Anda untuk melakukan ini dalam jawaban ini dari Jakub Narębski . Yang mana yang paling nyaman tergantung pada berapa banyak komit yang ingin Anda kembalikan, dan metode mana yang paling masuk akal bagi Anda.

Karena dari pertanyaan Anda, sudah jelas bahwa Anda sudah terbiasa git reset --hardmengatur ulang mastercabang Anda, Anda mungkin perlu mulai dengan menggunakan git reset --hard ORIG_HEADuntuk memindahkan cabang Anda kembali ke tempat sebelumnya. (Seperti biasa dengan git reset --hard, pastikan itugit status bersih, bahwa Anda berada di cabang kanan dan bahwa Anda sadar git reflogsebagai alat untuk memulihkan komit yang tampaknya hilang.) Anda juga harus memeriksa ORIG_HEADtitik - titik ke komit yang tepat, dengan git show ORIG_HEAD.

Penyelesaian masalah:

Jika Anda mendapatkan pesan seperti " ! [Remote ditolak] a60f7d85 -> master (kait pra-terima ditolak) "

maka Anda harus mengizinkan penulisan ulang riwayat cabang untuk cabang tertentu. Dalam BitBucket misalnya dikatakan "Menulis ulang sejarah cabang tidak diperbolehkan". Ada kotak centang bernama Allow rewriting branch historyyang harus Anda periksa.

Mark Longair
sumber
21
Bahaya bahaya: reset ini mengasumsikan bahwa cabang ( pelacakan ) yang sesuai saat ini dicentang dan tidak ada perubahan yang tidak berkomitmen yang ingin Anda pertahankan. Gunakan git update-refsebagai gantireset --hard ; itu akan memungkinkan Anda untuk melakukan hal yang sama tanpa memiliki pohon yang bekerja / memeriksa cabang
sehe
3
Saya melihat. Itu telah didorong dan diubah oleh orang lain. Jadi saya harus menggunakan revert tetapi katakanlah saya ingin mengembalikan 4 komitmen terakhir jadi saya harus melakukan git revert comit1; git push; git revert comit2; git push; ...atau hanya git revert commit4; git push?
nacho4d
1
@ nacho4d: Anda tidak perlu mendorong setelah setiap pemulihan - ada uraian bagus tentang apa yang harus dilakukan dalam jawaban ini dari Jakub Narębski . Anda harus mengembalikan setiap komit ke belakang - cukup lakukan git revert commit4menciptakan komit baru yang hanya membatalkan perubahan yang diperkenalkan commit4. Namun, sebagai jawaban yang saya tautkan ke poin, Anda dapat menggulung ini menjadi satu komit.
Mark Longair
1
@Mark saya sudah menjalankan git reset --hardtetapi saya telah menghapus lokal saya dan menarik dari asal lagi sehingga saya dapat melakukan git revert ...keraguan saya sekarang adalah: apakah saya harus mengembalikan setiap komit dan mendorong (satu per satu) atau hanya mengembalikan komit pertama setelah hanya komit saja?
nacho4d
1
@ Sehe: sulit digunakan karena Anda perlu menggunakan nama .gitreferensi lengkap, dan jadi mudah bagi orang untuk membuang sampah sembarangan pada direktori mereka dengan referensi yang tidak ingin mereka buat. Saya salah mengatakan bahwa tidak ada pemeriksaan keamanan. Anda dapat menemukan klasifikasi menjadi perintah "plumbing" dan "porcelain" di halaman git man .
Mark Longair
123

Gunakan jawaban lain jika Anda tidak keberatan kehilangan perubahan lokal. Metode ini masih dapat merusak remote Anda jika Anda memilih hash komit yang salah untuk kembali.

Jika Anda hanya ingin membuat kecocokan remote komit di mana saja di repo lokal Anda:

  1. Apakah tidak melakukan ulang apapun.
  2. Gunakan git loguntuk menemukan komit yang ingin Anda tuju. git log -puntuk melihat perubahan, atau git log --graph --all --oneline --decorateuntuk melihat pohon kompak.
  3. Salin hash atau tagnya, atau nama cabangnya jika ini tipnya.
  4. Jalankan perintah seperti:

    git push --force <remote> <commit-ish>:<the remote branch>
    

    misalnya

    git push --force origin 606fdfaa33af1844c86f4267a136d4666e576cdc:master
    

    atau

    git push --force staging v2.4.0b2:releases
    

Saya menggunakan alias ( git go) yang nyaman untuk melihat riwayat seperti pada langkah 2, yang dapat ditambahkan seperti:

    git config --global alias.go 'log --graph --all --decorate --oneline'`
Walf
sumber
3
Grafiknya adalah tip yang sangat bagus, saya hanya menambahkan -5 untuk mendapatkan hanya komit n terakhir, itu pohon besar. Juga menghindari reset adalah apa yang saya cari. Hebat
AlexanderD
@AlexanderD Anda juga bisa menambahkan alias ke Git daripada shell Anda, jadi ini berfungsi di mana-mana. Git memahami alias tersebut dan tab-selesai dari perintah lengkap sehingga Anda dapat menambahkan argumen. git config --global alias.graph 'log --graph --all --decorate --oneline'kurang berantakan dan Anda masih dapat membatasinya, misalnya:git graph -5
Walf
Ini sempurna. Saya selalu mengacaukan lokal saya. Ini adalah persis apa yang saya butuhkan setelah secara tidak sengaja mendorong pementasan saya untuk hidup :( Terima kasih!
Jake
1
Pada Windows, masukkan quntuk keluar dari log git. 2 menit saya tidak akan pernah kembali.
dst3p
1
@ dst3p Itu ada di setiap platform, sobat. Program pager biasanya lessdan qmerupakan cara normal untuk keluar. Git Bash seperti terminal * nix.
Walf
63

Saya memecahkan masalah seperti Anda dengan perintah ini:

git reset --hard <commit-hash> 
git push -f <remote> <local branch>:<remote branch> 
Ibrohim Ermatov
sumber
13

Di GitLab, Anda mungkin harus mengatur cabang Anda untuk tidak terlindungi sebelum melakukan ini. Anda dapat melakukan ini di [repo]> Pengaturan> Repositori> Cabang yang Dilindungi. Kemudian metode dari jawaban Mark bekerja.

git reset --hard <commit-hash>
git push -f origin master
dudasaus
sumber
10

Jika Anda ingin versi file sebelumnya, saya akan merekomendasikan menggunakan checkout git.

git checkout <commit-hash>

Melakukan hal ini akan mengirim Anda kembali ke masa lalu, itu tidak mempengaruhi keadaan proyek Anda saat ini, Anda dapat datang ke mainline git checkout mainline

tetapi ketika Anda menambahkan file dalam argumen, file itu dibawa kembali kepada Anda dari waktu sebelumnya ke waktu proyek Anda saat ini, yaitu proyek Anda saat ini diubah dan perlu dilakukan.

git checkout <commit-hash> -- file_name
git add .
git commit -m 'file brought from previous time'
git push

Keuntungannya adalah ia tidak menghapus histori, dan juga tidak mengembalikan perubahan kode tertentu (git revert)

Lihat lebih lanjut di sini https://www.atlassian.com/git/tutorials/undoing-changes#git-checkout

priya khokher
sumber
Ini adalah jawaban yang sangat bagus: itu bekerja, titik dan sangat aman; jika Anda mengacaukannya, mudah untuk kembali.
bob
8

Dua sen saya untuk jawaban sebelumnya: jika

git push --force <remote> <the-hash>:<the remote branch>

masih tidak berfungsi, Anda mungkin ingin mengedit <your-remote-repo>.git/configbagian penerimaan file:

[receive]
  #denyNonFastforwards = true
  denyNonFastforwards = false
badbishop
sumber
Sangat membantu untuk mengetahui cara mengkonfigurasi remote untuk memungkinkan push non-fast-forward karena sebagian besar jawaban tampaknya menganggap layanan remote seperti github atau bitbucket.
strongbutgood
2

Jika cabang Anda bukan pengembangan atau produksi, cara termudah untuk mencapai ini adalah mengatur ulang ke komit tertentu secara lokal dan membuat cabang baru dari sana. Kamu bisa menggunakan:

git checkout 000000

(di mana 000000 adalah id komit di mana Anda ingin pergi) di cabang bermasalah Anda dan kemudian cukup buat cabang baru:

git remote menambahkan [name_of_your_remote]

Kemudian Anda dapat membuat PR baru dan semuanya akan berfungsi dengan baik!

Gerardo Suarez
sumber
1

Lakukan satu hal, dapatkan nomor komitnya SHA no. seperti 87c9808 dan kemudian,

  1. gerakkan diri Anda, itu kepala Anda ke komit yang ditentukan (dengan melakukan git reset --hard 89cef43 // sebutkan nomor Anda di sini)
  2. Selanjutnya lakukan beberapa perubahan dalam file acak, sehingga git akan meminta Anda untuk melakukan itu secara lokal dan kemudian dari jarak jauh Jadi, apa yang perlu Anda lakukan sekarang adalah. setelah menerapkan perubahan git commit -a -m "trial commit"
  3. Sekarang tekan komit berikut (jika ini telah dilakukan secara lokal) oleh git push master asal
  4. Sekarang apa yang git akan minta dari Anda adalah itu

galat: gagal mendorong beberapa referensi ke ' https://github.com/YOURREPOSITORY/AndroidExperiments.git ' petunjuk: Pembaruan ditolak karena ujung cabang Anda saat ini berada di belakang petunjuk: mitra jarak jauh. Integrasikan perubahan jarak jauh (mis. Petunjuk: 'git pull ...') sebelum mendorong lagi. **

  1. Jadi sekarang yang bisa Anda lakukan adalah

git push --force origin master

  1. Dan dengan demikian, saya harap ini berhasil :)
Siddharth Choudhary
sumber
1

Sourcetree: mengatur ulang remote ke komit tertentu

  1. Jika Anda telah mendorong komit buruk ke remote Anda (asal / fitur / 1337_MyAwesomeFeature) seperti di bawah gambar

Pergi ke Remote

  1. Pergi ke Remote> asal> fitur> 1337_MyAwesomeFeature
  2. Klik kanan dan pilih "Hapus asal / fitur / 1337_MyAwesomeFeature" (Atau ubah nama jika ingin cadangan dan lewati langkah 4.)
  3. Klik "Paksa hapus" dan "OK".

masukkan deskripsi gambar di sini masukkan deskripsi gambar di sini

  1. Pilih komit lama Anda dan pilih "Reset cabang saat ini ke komit ini"
  2. Pilih mode mana yang ingin Anda miliki (Sulit jika Anda tidak ingin perubahan terakhir Anda) dan "OK".

masukkan deskripsi gambar di sini masukkan deskripsi gambar di sini

  1. Dorong komit ini ke sumber / fitur baru / 1337_MyAwesomeFeature masukkan deskripsi gambar di sini

  2. Cabang fitur lokal Anda dan cabang fitur jarak jauh Anda sekarang berada di komit sebelumnya (pilihan Anda) masukkan deskripsi gambar di sini

Joel Wiklund
sumber