Melakukan kembali penggabungan yang dikembalikan di Git

231

Saya mengalami sedikit masalah di sini: Saya punya cabang khusus masalah 28sdi Git, yang saya gabungkan di developcabang umum . Ternyata saya melakukannya terlalu cepat, jadi saya menggunakan git-revert untuk membatalkan penggabungan. Sekarang, bagaimanapun, waktunya telah datang untuk menggabungkan 28ske dalam develop, tetapi perintah git-merge melihat penggabungan asli, dan dengan senang hati mengumumkan bahwa semuanya baik-baik dan cabang telah sudah bergabung. Apa yang saya lakukan sekarang? Buat komit 'Kembalikan "Kembalikan" 28s -> mengembangkan ""? Tampaknya bukan cara yang baik untuk melakukannya, tetapi saya tidak bisa membayangkan yang lain saat ini.

Seperti apa bentuk struktur pohon:

Output log git

Toms Mikoss
sumber
4
Ini GitX ( gitx.frim.nl ).
Toms Mikoss

Jawaban:

169

Anda harus "mengembalikan pengembalian". Tergantung pada Anda bagaimana mengembalikan aslinya, mungkin tidak semudah kedengarannya. Lihatlah dokumen resmi tentang topik ini .

---o---o---o---M---x---x---W---x---Y
              /
      ---A---B-------------------C---D

untuk memungkinkan:

---o---o---o---M---x---x-------x-------*
              /                       /
      ---A---B-------------------C---D

Tetapi apakah itu semua berhasil? Tentu saja. Anda dapat mengembalikan gabungan, dan dari sudut teknis murni, git melakukannya dengan sangat alami dan tidak memiliki masalah nyata.
Itu hanya menganggapnya sebagai perubahan dari "negara sebelum penggabungan" ke "negara setelah penggabungan", dan hanya itu.
Tidak ada yang rumit, tidak ada yang aneh, tidak ada yang benar-benar berbahaya. Git akan melakukannya tanpa memikirkannya.

Jadi dari sudut teknis, tidak ada yang salah dengan mengembalikan penggabungan, tetapi dari sudut alur kerja itu adalah sesuatu yang biasanya harus Anda hindari .

Jika memungkinkan, misalnya, jika Anda menemukan masalah yang digabungkan ke pohon utama, alih-alih mengembalikan gabungan, berusaha sangat keras untuk :

  • membagi dua masalah ke cabang yang Anda gabungkan, dan perbaiki saja,
  • atau coba kembalikan komit individu yang menyebabkannya.

Ya, itu lebih kompleks, dan tidak ada, itu tidak selalu akan bekerja (kadang-kadang jawabannya adalah: "oops, aku benar-benar seharusnya tidak bergabung, karena itu belum siap, dan saya benar-benar harus membatalkan semua dari menggabungkan"). Jadi Anda benar-benar harus mengembalikan penggabungan, tetapi ketika Anda ingin melakukan kembali penggabungan, Anda sekarang harus melakukannya dengan mengembalikan pengembalian.

J-16 SDiZ
sumber
10
Tautan baik (+1). Saya mengambil kebebasan untuk menyalin bagian dari dokumen dalam jawaban Anda untuk memungkinkan pembaca melihat dengan segera opsi yang relevan dalam kasus ini. Jika Anda tidak setuju, silakan kembali.
VonC
5
Kami baru saja menemukan sebuah kasus di mana kami perlu melakukan ini dan menemukan bahwa kesenangan tidak berhenti di sini. Itu adalah cabang berjalan lama yang digabungkan, jadi kami harus terus memperbaruinya. Pendekatan saya di sini: tech.patientslikeme.com/2010/09/29/...
jdwyah
Saya mengikuti posting blog @ jdwyah dan itu mulia (serius, itu mengagumkan bahwa itu hanya bekerja).
hellatan
2
@jdwyah yang tampaknya merupakan tautan yang terputus, tetapi kedengarannya seperti bacaan yang menarik. Berikut adalah mirror archive.org tetapi gambarnya hilang: web.archive.org/web/20111229193713/http://…
Alex KeySmith
15
Blog post telah dibangkitkan, terima kasih: blog.jdwyah.com/2015/07/dealing-with-git-merge-revisions.html
jdwyah
53

Anggaplah Anda memiliki sejarah seperti itu

---o---o---o---M---W---x-------x-------*
              /                      
      ---A---B

Di mana A, B gagal melakukan dan W - adalah pengembalian dari M

Jadi sebelum saya mulai memperbaiki masalah yang ditemukan, saya memilih cherry-pick dari commit ke cabang saya

git cherry-pick -x W

Lalu saya mengembalikan W commit di cabang saya

git revert W 

Setelah itu saya bisa terus memperbaiki.

Sejarah terakhir bisa terlihat seperti:

---o---o---o---M---W---x-------x-------*
              /                       /     
      ---A---B---W---W`----------C---D

Ketika saya mengirim PR, itu akan dengan jelas menunjukkan bahwa PR tidak dapat dikembalikan dan menambahkan beberapa komitmen baru.

Maksim Kotlyar
sumber
3
Sepertinya ini bisa membantu, tetapi sangat jarang pada detail (apa C, D dalam diagram terakhir) sehingga lebih membuat frustrasi daripada berguna
Isochronous
4
@Isinkron C dan D tampaknya adalah komitmen yang memperbaiki masalah yang diperkenalkan oleh A dan B.
Thomas
@ Thomas tepatnya
Maksim Kotlyar
Adalah baik bahwa Anda telah disorot menggunakan PR dalam hal ini karena dapat memberikan 'pemeriksaan kewarasan' terakhir sebelum bergabung kembali untuk dikuasai.
Willem van Ketwich
gunakan mengapa Anda me-restart cabang Anda dari W asli? Yaitu, biarkan topik Anda melanjutkan dari W, dengan W` diikuti oleh C dan D? Itu menghilangkan beberapa duplikasi
Erik Carstensen
12

Untuk mengembalikan kembali tanpa mengacaukan alur kerja Anda terlalu banyak:

  • Buat salinan sampah lokal dari pengembangan
  • Kembalikan komit pengembalian pada salinan pengembangan lokal
  • Gabungkan salinan itu ke cabang fitur Anda, dan dorong cabang fitur Anda ke server git Anda.

Cabang fitur Anda sekarang harus dapat digabung seperti biasa ketika Anda siap untuk itu. Satu-satunya downside di sini adalah bahwa Anda akan memiliki beberapa komitmen gabungan / pengembalian dalam sejarah Anda.

Sam Dufel
sumber
Hanya untuk mencegah campur-baur lebih lanjut, saya juga membuat salinan 'sampah' dari cabang fitur saya dan menggabungkan pengembangan yang dikembalikan ke dalamnya.
jhhwilliams
Terima kasih! Ini adalah satu-satunya jawaban yang benar-benar menjelaskan cara melakukannya daripada mengatakan Anda tidak harus melakukan ini. Sangat membantu.
Emmy
Terima kasih, ini sangat membantu saya. :)
Daniel Stracaboško
11

Untuk mengembalikan kembali di GIT:

git revert <commit-hash-of-previous-revert>
Richard
sumber
1
Menggunakan ini di cabang kerja saya untuk mengembalikan revert, lalu PR baru untuk dikembangkan. Sekarang git melihat semua perubahan yang ada di PR sebelumnya yang dikembalikan. Terima kasih.
Danstan
3

Alih-alih menggunakan git-revertAnda bisa menggunakan perintah ini di develcabang untuk membuang (membatalkan) komit gabungan yang salah (bukan hanya mengembalikannya).

git checkout devel
git reset --hard COMMIT_BEFORE_WRONG_MERGE

Ini juga akan menyesuaikan isi direktori kerja sesuai. Hati-hati :

  • Simpan perubahan Anda di cabang berkembang (karena penggabungan yang salah) karena mereka juga akan terhapus oleh git-reset. Semua dilakukan setelah yang Anda tentukan sebagai git resetargumen akan hilang!
  • Juga, jangan lakukan ini jika perubahan Anda sudah ditarik dari repositori lain karena reset akan menulis ulang riwayat.

Saya merekomendasikan untuk mempelajari git-reset manual dengan seksama sebelum mencoba ini.

Sekarang, setelah reset Anda dapat menerapkan kembali perubahan Anda di develkemudian lakukan

git checkout devel
git merge 28s

Ini akan menjadi penggabungan nyata dari 28smenjadi develseperti yang awal (yang sekarang terhapus dari sejarah git).

knweiss
sumber
8
Bagi siapa saja yang tidak super akrab dengan git dan mungkin ingin mengikuti petunjuk ini: hati-hati dengan menggabungkan reset --harddan push origin. Ketahuilah bahwa dorongan kekuatan ke asalnya mungkin benar-benar membuat PR terbuka di GitHub.
funroll
Sangat membantu untuk memperbaiki beberapa masalah penggabungan pada server git pribadi. Terima kasih!
mix3d
1
+1 untuk teknik ini. Berpotensi merusak, tetapi bisa menyelamatkan Anda dari banyak sakit kepala (dan sejarah yang hancur) saat diterapkan dengan bijaksana.
siliconrockstar
1

Saya baru saja menemukan posting ini ketika menghadapi masalah yang sama. Saya menemukan cara di atas menakutkan untuk melakukan reset hards dll. Saya akhirnya akan menghapus sesuatu yang saya tidak mau, dan tidak akan bisa mendapatkannya kembali.

Sebaliknya aku memeriksa komit saya ingin cabang untuk kembali ke misalnya git checkout 123466t7632723. Kemudian dikonversi ke cabang git checkout my-new-branch. Saya kemudian menghapus cabang yang tidak saya inginkan lagi. Tentu saja ini hanya akan berhasil jika Anda dapat membuang cabang yang Anda rusak.

Claire
sumber
1
Ini git reflogakan melindungi Anda pada hard reset selama beberapa bulan jika Anda kemudian menemukan bahwa Anda membutuhkan komitmen yang hilang. Reflog terbatas pada repo lokal Anda.
Todd
1

Saya akan menyarankan Anda untuk mengikuti langkah-langkah di bawah ini untuk memulihkan kembali, katakan SHA1.

git checkout develop #go to develop branch
git pull             #get the latest from remote/develop branch
git branch users/yourname/revertOfSHA1 #having HEAD referring to develop
git checkout users/yourname/revertOfSHA1 #checkout the newly created branch
git log --oneline --graph --decorate #find the SHA of the revert in the history, say SHA1
git revert SHA1
git push --set-upstream origin users/yourname/revertOfSHA1 #push the changes to remote

Sekarang buat PR untuk cabang users/yourname/revertOfSHA1

Venkataraman R
sumber
1
  1. buat cabang baru di komit sebelum penggabungan asli - sebut saja 'mengembangkan-basis'
  2. melakukan rebase interaktif 'mengembangkan' di atas 'mengembangkan-basis' (meskipun sudah ada di atas). Selama rebase interaktif, Anda akan memiliki kesempatan untuk menghapus kedua komit gabungan, dan komit yang membalikkan gabungan, yaitu menghapus kedua peristiwa dari sejarah git

Pada titik ini Anda akan memiliki cabang 'kembangkan' yang bersih tempat Anda dapat menggabungkan fitur brach Anda seperti yang biasa Anda lakukan.

Misha Mostov
sumber
Pendekatan ini akan menimbulkan masalah jika cabang berkembang dibagi dengan yang lain.
PSR