Batalkan gabungan dengan permintaan tarik?

159

Seseorang menerima permintaan tarik yang seharusnya tidak mereka miliki. Sekarang kami memiliki banyak kode yang rusak digabung. Bagaimana Anda membatalkan permintaan tarik? Saya hanya akan mengembalikan perubahan ke komit tepat sebelum penggabungan, tetapi saya perhatikan bahwa itu bergabung dalam banyak komit. Jadi sekarang ada semua komitmen dari orang ini dari beberapa hari sebelum penggabungan. Bagaimana Anda membatalkan ini?

Akan
sumber
7
Terlepas dari saran dari jawaban yang diterima, TOLONG jangan paksa-mendorong ke repositori jika repo dibagi dengan orang lain. Anda berisiko merusak pekerjaan yang telah dilakukan orang lain, dan GitHub dapat terus menunjukkan bahwa permintaan tarik telah digabungkan. Jawaban lain untuk pertanyaan ini menjelaskan cara yang lebih aman untuk membatalkan permintaan tarik.
alxndr
2
Catatan: setidaknya sekarang (Juni 2014), GitHub mengusulkan tombol "Kembalikan" di GUI web Permintaan Tarik mereka. Lihat jawaban saya di bawah ini
VonC
1
Masalah dengan tombol revert adalah ia menciptakan komit baru sebagai kebalikan dari permintaan pull, yang berarti bahwa jika Anda ingin menggabungkan perubahan ini pada akhirnya, menggunakan tombol "Revert" dapat membuat hal itu menjadi jauh lebih sulit.
FluffySamurai

Jawaban:

159

Ada jawaban yang lebih baik untuk masalah ini, meskipun saya bisa memecahnya langkah demi langkah.

Anda perlu mengambil dan memeriksa perubahan hulu terbaru seperti itu, misalnya:

git fetch upstream
git checkout upstream/master -b revert/john/foo_and_bar

Melihat log komit, Anda harus menemukan sesuatu yang mirip dengan ini:

commit b76a5f1f5d3b323679e466a1a1d5f93c8828b269
Merge: 9271e6e a507888
Author: Tim Tom <[email protected]>
Date:   Mon Apr 29 06:12:38 2013 -0700

    Merge pull request #123 from john/foo_and_bar

    Add foo and bar

commit a507888e9fcc9e08b658c0b25414d1aeb1eef45e
Author: John Doe <[email protected]>
Date:   Mon Apr 29 12:13:29 2013 +0000

    Add bar

commit 470ee0f407198057d5cb1d6427bb8371eab6157e
Author: John Doe <[email protected]>
Date:   Mon Apr 29 10:29:10 2013 +0000

    Add foo

Sekarang Anda ingin mengembalikan seluruh permintaan tarik dengan kemampuan untuk membatalkan kembali nanti. Untuk melakukannya, Anda harus mengambil ID komit gabungan .

Dalam contoh di atas komit gabungan adalah yang teratas di mana dikatakan "Permintaan tarik gabungan # 123 ..." .

Lakukan ini untuk mengembalikan kedua perubahan ( "Tambahkan bilah" dan "Tambahkan foo" ) dan Anda akan berakhir dengan satu komit mengembalikan seluruh permintaan tarik yang dapat Anda batalkan kembali nanti dan menjaga riwayat perubahan tetap bersih:

git revert -m 1 b76a5f1f5d3b323679e466a1a1d5f93c8828b269
errordeveloper
sumber
6
Ini seharusnya jawaban yang benar. Ada referensi di halaman manual git-revert untuk lebih jelasnya dari milis git di sini kernel.org/pub/software/scm/git/docs/howto/…
Justin Hamade
2
Mengapa git checkout upstream/master -b revert/john/foo_and_bar? apa fungsinya sebenarnya?
Magne
4
@Magne - Anda sedang membuat cabang baru untuk melakukan pengembalian, yang kemudian dapat Anda pilih tempat untuk menggabungkan pengembalian. Pada dasarnya hanya memberi Anda lebih banyak kendali tentang apa yang harus dilakukan dengan cabang. Dalam kasus saya, saya mengajukan permintaan tarikan baru dari cabang "tetap" yang berisi pengembalian kembali ke cabang pengembangan kami, yang berarti permintaan tarikan baru saya juga dapat dikembalikan jika perlu. Ini dilakukan untuk rilis di mana kami memutuskan untuk mengeluarkan draf pertama dari fitur yang dijadwal ulang. Tidak ada kode buruk, hanya saja tidak ada dalam rilis ini.
Daniel Nalbach
3
Saya belajar pelajaran sulit tentang ini. Kami mendorong fitur ke cabang pengembangan kami tetapi menyadari ada masalah data dan kembali langsung pada pengembangan. Kemudian ketika hal-hal diperbaiki, kami ingin menambahkan fitur pengembangan yang lebih baru kembali ke cabang ini untuk menguji kompatibilitasnya dengan fitur ini sebelum mendorong, jadi saya menggabungkan pengembangan kembali ke cabang fitur. Ini juga menerapkan komit pengembalian, yang tidak mencatat setiap perubahan yang dibuat ke cabang fitur. > <
Greg
86

Lihatlah grafik komit Anda (dengan gitk atau program serupa). Anda akan melihat komit dari permintaan tarik, dan Anda akan melihat komit Anda sendiri, dan komit gabungan (jika itu bukan gabungan fast-forward). Anda hanya perlu menemukan komit terakhir sebelum penggabungan, dan setel ulang cabang ke komit ini.

(Jika Anda memiliki reflog cabang, akan lebih mudah untuk menemukan komit sebelum penggabungan.)


(Edit setelah informasi lebih lanjut dalam komentar :)

Oke, mari kita lihat grafik:

tangkapan layar 1

Saya menganggap komit terakhir (paling kanan) adalah penggabungan salah Anda dengan permintaan tarik , yang menggabungkan garis biru yang terlihat di sini. Komitmen baik terakhir Anda adalah yang sebelumnya di garis hitam, di sini ditandai dengan merah:

masukkan deskripsi gambar di sini

Setel ulang ke komit ini, dan Anda akan baik-baik saja.

Ini berarti, dalam copy pekerjaan lokal Anda, lakukan ini (setelah memastikan Anda tidak memiliki hal-hal yang tidak dikomit lagi, misalnya dengan simpanan git):

git checkout master
git reset --hard 7a62674ba3df0853c63539175197a16122a739ef
gitk 

Sekarang konfirmasikan bahwa Anda benar-benar di komit yang saya tandai di sana, dan Anda tidak akan melihat satu pun dari barang yang ditarik dalam leluhurnya.

git push -f origin master

(jika remote github Anda dinamai origin- lain ubah nama).

Sekarang semuanya akan terlihat benar di github juga. Komit masih akan berada di repositori Anda, tetapi tidak dapat dijangkau oleh cabang mana pun, sehingga tidak akan membahayakan di sana. (Dan mereka akan tetap di repositori RogerPaladin, tentu saja.)

(Mungkin ada satu-satunya cara khusus web Github untuk melakukan hal yang sama, tapi saya tidak terlalu akrab dengan Github dan sistem pengelolaan permintaan tariknya.)

Perhatikan bahwa jika ada orang lain yang mungkin telah menarik tuan Anda dengan komit yang salah, mereka kemudian memiliki masalah yang sama seperti Anda saat ini, dan tidak dapat benar-benar berkontribusi kembali. sebelum mengatur ulang ke versi master baru Anda.

Jika kemungkinan ini terjadi, atau Anda hanya ingin menghindari masalah, gunakan git revertperintah alih-alih git reset, untuk mengembalikan perubahan dengan komit baru, alih-alih mengembalikan ke yang lebih lama. (Beberapa orang berpikir Anda tidak boleh melakukan reset dengan cabang yang diterbitkan.) Lihat jawaban lain untuk pertanyaan ini tentang bagaimana melakukan ini.

Demi masa depan:

Jika Anda ingin hanya beberapa komit dari cabang RogerPaladin ini, pertimbangkan untuk menggunakan cherry-pickbukan merge. Atau berkomunikasi dengan RogerPaladin untuk memindahkan mereka ke cabang terpisah dan mengirim permintaan tarik baru.

Paŭlo Ebermann
sumber
Tapi kami memiliki banyak komitmen antara merger dan komit pertamanya. Jadi seperti kita memiliki komit gabungan, komit kita sendiri dan kemudian komit lain olehnya. Sepertinya itu bergabung dalam komitmennya yang sangat lama.
Akan
Ya, itu akan menggabungkan semua yang merupakan leluhur dari komit gabungan (dan belum menjadi leluhur dari komit Anda). Ini seharusnya tidak menghalangi Anda untuk mengatur ulang - komit tidak akan disusun ulang sendiri, jika Anda tidak melakukan rebase setelahnya.
Paŭlo Ebermann
1
Ya, sekarang ini terlihat benar (terlepas dari penggabungan yang aneh ke dalam dirinya sendiri - tetapi ini mungkin merupakan kesalahan dalam perangkat lunak grafik jaringan). :-) Saya senang saya bisa membantu.
Paŭlo Ebermann
6
Saya pikir ini mungkin bermasalah jika seseorang telah menarik komitmen buruk dan mereka kemudian mengirim permintaan tarik yang berisi komitmen buruk yang sama, sehingga mereka menyelinap tetapi ke repo. Tidakkah lebih aman untuk membuat komit baru yang membalikkan komitmen buruk? Dengan begitu, jika komitmen buruk telah ditarik ke cabang / garpu lain, mereka akan dihapus secara efektif dengan tarikan lain ke cabang / garpu lain itu? Saya tidak menyatakan ini sebagai fakta, ini adalah apa yang saya pikir mungkin benar, berada di posisi yang sama dengan OP dan telah menghabiskan satu jam atau lebih mempertimbangkan opsi saya.
Myles McDonnell
4
@Saya akan menyarankan untuk tidak menerima jawaban ini. Ini bagus untuk kode yang belum didorong (dalam hal ini , ini adalah pertanyaan SO yang lebih relevan, tetapi untuk kode yang dibagikan secara publik, melakukan perintah git yang menulis ulang sejarah (dalam kasus ini, reset --harddan dorongan gaya adalah latihan yang sangat buruk) Jawaban oleh @errordeveloper di bawah ini menunjukkan cara untuk melakukan ini tanpa menulis ulang sejarah atau memaksakan dorongan.
asmeurer
34

Jika tarikan adalah hal terakhir yang dia lakukan saat itu

git reset --hard HEAD~1
samthebest
sumber
3
hati-hati mengikuti instruksi ini, itu benar-benar membuat saya mundur 2 langkah, bukan satu.
szeitlin
1
@szeitlin Bagaimana mungkin itu membuat Anda kembali 2 langkah, bukan satu? Saya tahu komentar ini ditinggalkan 4+ tahun yang lalu, tetapi saya ingin tahu apakah ada yang tahu jawaban bagaimana hal itu mungkin terjadi. Ini sangat penting bagi saya. Terima kasih.
Haradzieniec
Saya tidak ingat sekarang, tapi saya kira itu bisa terjadi jika saya membuat komit baru ketika saya mencoba mengatur ulang? Saya hanya akan mengujinya dengan repo tiruan jika Anda khawatir tentang hal itu.
szeitlin
Yang ini bekerja dengan baik untuk saya. Itu menghapus permintaan tarik yang baru saja digabungkan. Setelah itu git reset --hard HEAD~1, saya biasa git push origin -fmemperbarui repositori jarak jauh. Tapi hati-hati, berhati-hatilah sebelum melakukan ini.
Denis Oluka
24

Mulai 24 Juni 2014, Anda dapat mencoba membatalkan PR dengan mudah (Lihat " Mengembalikan permintaan tarik ") dengan:

Memperkenalkan Tombol Kembalikan

Anda dapat dengan mudah mengembalikan permintaan tarik di GitHub dengan mengklik Kembalikan:

https://camo.githubusercontent.com/0d3350caf2bb1cba53123ffeafc00ca702b1b164/68747470733a2f2f6769746875622d696d616765732e73332e616d617a6f6e6177732e636f6d2f68656c702f70756c6c5f72657175657374732f7265766572742d70756c6c2d726571756573742d6c696e6b2e706e67

Anda akan diminta untuk membuat permintaan tarik baru dengan perubahan yang dikembalikan:

https://camo.githubusercontent.com/973efae3cc2764fc1353885a6a45b9a518d9b78b/68747470733a2f2f6769746875622d696d616765732e73332e616d617a6f6e6177732e636f6d2f68656c702f70756c6c5f72657175657374732f7265766572742d70756c6c2d726571756573742d6e65772d70722e706e67

Masih harus diuji apakah itu mengembalikan penggunaan -matau tidak (untuk mengembalikan gabungan juga)

Namun Adil H Raza menambahkan dalam komentar (Desember 2019):

Itulah perilaku yang diharapkan, itu membuat cabang baru dan Anda dapat membuat PR dari cabang baru ini ke Anda master.
Dengan cara ini di masa depan Anda dapat membatalkan pemulihan kembali jika perlu, itu adalah opsi paling aman dan tidak langsung mengubah Anda master.


Peringatan : Korayem tunjukkan dalam komentar bahwa:

Setelah kembali, katakanlah Anda melakukan beberapa perubahan lebih lanjut pada cabang Git dan membuat PR baru dari cabang sumber / tujuan yang sama.
Anda akan menemukan PR hanya menampilkan perubahan baru, tetapi tidak ada apa pun yang ada di sana sebelum kembali .

Korayem merujuk kita ke " Github: Perubahan yang diabaikan setelah kembali ( git cherry-pick, git rebase) " untuk lebih.

VONC
sumber
saya mencoba ini dan itu membuat cabang baru bukannya membatalkan PR pada master?
Грозный
Aneh. Bisakah Anda mengajukan pertanyaan baru untuk menggambarkan perilaku itu?
VonC
itu adalah perilaku yang diharapkan, itu membuat cabang baru dan Anda dapat membuat PR dari cabang baru ini ke master Anda. Dengan cara ini di masa depan Anda dapat membatalkan pemulihan kembali jika perlu, itu adalah opsi paling aman dan tidak langsung mengubah master Anda.
Adil H. Raza
1
@ AdilH.Raza Terima kasih. Saya telah memasukkan komentar Anda dalam jawaban untuk lebih banyak visibilitas.
VonC
1
@VonC menyilangkan jari ini akan menyelamatkan pengembang di seluruh dunia dari terlalu banyak penderitaan dan pemborosan waktu
Korayem
8

Untuk membatalkan permintaan tarik github dengan komit yang tidak ingin Anda hapus, Anda harus menjalankan:

git reset --hard --merge <commit hash>

dengan hash komit menjadi PRIOR komit untuk menggabungkan permintaan tarik. Ini akan menghapus semua komitmen dari permintaan tarik tanpa mempengaruhi komitmen apa pun dalam riwayat.

Cara yang baik untuk menemukan ini adalah dengan membuka permintaan tarik yang sudah ditutup dan menemukan bidang ini:

Tarik Gambar Permintaan Tarik Gambar Permintaan

Setelah Anda menjalankan git reset, jalankan:

git push origin --force <branch name>

Ini harus mengembalikan cabang sebelum permintaan tarik TANPA memengaruhi komit apa pun di cabang yang dibubuhi riwayat komit antara komitmen dari permintaan tarik.

EDIT:

Jika Anda mengklik tombol balik pada permintaan tarik, ini menciptakan komit tambahan pada cabang. TIDAK JANGAN komit atau unmerge. Ini berarti bahwa jika Anda menekan tombol kembali, Anda tidak dapat membuka permintaan tarik baru untuk menambahkan kembali semua kode ini.

Fluffy Samurai
sumber
Cara luar biasa untuk
membereskan
Terima kasih! Itu adalah apa yang saya rencanakan untuk dilakukan, tetapi itu akan menjadi sekitar ~ 200 komitmen untuk memilih cherry.
FluffySamurai
1

Saya menggunakan tempat ini sepanjang waktu, terima kasih.

Saya sedang mencari cara membatalkan permintaan tarik dan sampai di sini.

Aku baru saja akan git reset --hard akan "sudah lama" dan melakukan fast forward kembali ke tempat saya sebelum melakukan permintaan tarik.

Selain mencari di sini, saya juga bertanya kepada rekan kerja saya apa yang akan dia lakukan, dan dia memiliki jawaban yang biasanya bagus: menggunakan contoh output pada jawaban pertama di atas:

git reset --hard 9271e6e

Seperti kebanyakan hal di Git, jika Anda melakukannya dengan cara yang tidak mudah, Anda mungkin salah melakukannya.

Mike Marshall
sumber