Git Cherry-pick vs Merge Workflow

302

Dengan asumsi saya adalah pengelola repo, dan saya ingin menarik perubahan dari kontributor, ada beberapa alur kerja yang mungkin:

  1. Saya cherry-pickmasing-masing komit dari remote (dalam urutan). Dalam hal ini git mencatat komit sebagai tidak terkait dengan cabang jarak jauh.
  2. I mergecabang, menarik semua perubahan, dan menambahkan komit "konflik" baru (jika perlu).
  3. Saya mergemasing-masing komit dari cabang jarak jauh secara individual (lagi-lagi dalam urutan), yang memungkinkan konflik dicatat untuk setiap komit, bukannya dikelompokkan bersama sebagai satu.
  4. Untuk kelengkapan, Anda dapat melakukan rebase(sama seperti cherry-pickopsi?), Namun pemahaman saya adalah bahwa ini dapat menyebabkan kebingungan bagi kontributor. Mungkin itu menghilangkan opsi 1.

Dalam kedua kasus 2 dan 3, git mencatat sejarah cabang dari commit, tidak seperti 1.

Apa pro dan kontra antara menggunakan salah satu cherry-pickatau mergemetode yang dijelaskan? Pemahaman saya adalah bahwa metode 2 adalah norma, tetapi saya merasa bahwa menyelesaikan komit besar dengan satu gabungan "konflik", bukanlah solusi terbersih.

cmcginty
sumber

Jawaban:

297

Keduanya rebase(dan cherry-pick) dan mergememiliki kelebihan dan kekurangan mereka. Saya berdebat di mergesini, tapi ada baiknya memahami keduanya. (Lihat di sini untuk jawaban alternatif, argumentasi yang menyebutkan kasus mana rebaseyang lebih disukai.)

mergelebih disukai daripada cherry-pickdan rebasekarena beberapa alasan.

  1. Kekokohan . Identifikasi SHA1 dari commit mengidentifikasikannya tidak hanya dalam dan dari dirinya sendiri tetapi juga dalam kaitannya dengan semua komitmen lain yang mendahuluinya. Ini menawarkan Anda jaminan bahwa keadaan repositori pada SHA1 yang diberikan identik di semua klon. Tidak ada (secara teori) ada kemungkinan seseorang telah melakukan apa yang tampak seperti perubahan yang sama tetapi sebenarnya merusak atau membajak repositori Anda. Anda dapat memilih dalam perubahan individu dan kemungkinan besar sama, tetapi Anda tidak memiliki jaminan. (Sebagai masalah sekunder kecil, komit yang dipetik cherry akan memakan tempat ekstra jika orang lain mengambil cherry di komit yang sama lagi, karena keduanya akan hadir dalam sejarah bahkan jika copy pekerjaan Anda akhirnya identik.)
  2. Kemudahan penggunaan . Orang-orang cenderung memahami mergealur kerja dengan cukup mudah. rebasecenderung dianggap lebih maju. Yang terbaik untuk memahami keduanya, tetapi orang-orang yang tidak ingin menjadi ahli dalam kontrol versi (yang menurut pengalaman saya telah menyertakan banyak rekan yang sangat pandai dalam apa yang mereka lakukan, tetapi tidak ingin menghabiskan waktu ekstra) memiliki lebih mudah waktu hanya menyatu.

Bahkan dengan alur kerja yang sangat banyak rebasedan cherry-pickmasih berguna untuk kasus-kasus tertentu:

  1. Satu kelemahan mergeadalah sejarah yang berantakan. rebasemencegah serangkaian komitmen panjang yang tersebar di dalam sejarah Anda, seperti jika Anda secara berkala bergabung dalam perubahan orang lain. Itu sebenarnya tujuan utamanya saat saya menggunakannya. Apa yang Anda ingin sangat berhati-hati, tidak pernah rebasekode yang Anda bagikan dengan repositori lain. Setelah komit dibuat, pushorang lain mungkin telah berkomitmen di atasnya, dan rebasing paling-paling akan menyebabkan jenis duplikasi yang dibahas di atas. Paling buruk Anda bisa berakhir dengan repositori yang sangat membingungkan dan kesalahan halus itu akan membawa Anda waktu lama untuk menemukan.
  2. cherry-pick berguna untuk mengambil sampel sebagian kecil perubahan dari cabang topik yang pada dasarnya Anda putuskan untuk dibuang, tetapi menyadari ada beberapa bagian berguna.

Adapun lebih suka menggabungkan banyak perubahan lebih dari satu: itu hanya jauh lebih sederhana. Sangat membosankan untuk melakukan penggabungan perubahan individu setelah Anda mulai memiliki banyak perubahan. Resolusi gabungan di git (dan di Mercurial, dan di Bazaar) sangat sangat baik. Anda tidak akan mengalami masalah besar dengan menggabungkan bahkan cabang yang panjang sebagian besar waktu. Saya biasanya menggabungkan semuanya sekaligus dan hanya jika saya mendapatkan banyak konflik saya membuat cadangan dan menjalankan kembali sedikit demi sedikit menggabungkan. Bahkan kemudian saya melakukannya dalam potongan besar. Sebagai contoh nyata, saya memiliki seorang kolega yang memiliki 3 bulan perubahan untuk digabung, dan mendapat sekitar 9000 konflik dalam 250000 baris kode-basis. Apa yang kami lakukan untuk memperbaikinya adalah melakukan penggabungan nilai satu bulan pada satu waktu: konflik tidak menumpuk secara linear, dan melakukannya dalam potongan-potongan menghasilkan jauhkurang dari 9000 konflik. Itu masih banyak pekerjaan, tetapi tidak sebanyak mencoba melakukan satu komitmen pada suatu waktu.

quark
sumber
1
Sebenarnya, secara teori ada kemungkinan bahwa Mallory dapat merusak repositori Anda dengan membuat komit dengan SHA1 yang sama tetapi konten yang berbeda, itu mungkin tidak akan pernah terjadi dalam praktik. :)
Bombe
1
Ha :) Maksud saya, "secara teori peluangnya sangat rendah sehingga Anda bisa mengandalkannya untuk tidak terjadi", tetapi Anda benar bahwa itu berbunyi kocar-kacir.
quark
Apa pendapat Anda tentang "menggabungkan --squash"?
cmcginty
@Bombe Jika Mallory ingin sukses, dia harus secara khusus membangun komit asli dan komit kedua dengan SHA1 yang sama. Jadi pertanyaan lain mungkin: apa kemungkinan dua (agak) palsu muncul dan Anda tidak memperhatikan? ;)
João Portela
64
9000 konflik? Saya akan berhenti dari pekerjaan saya dan menjadi penjaga lebah.
Sebastian Patten
95

Menurut pendapat saya, memetik ceri harus disediakan untuk situasi langka di mana diperlukan, misalnya jika Anda melakukan beberapa perbaikan langsung pada cabang 'master' (trunk, cabang pengembangan utama) dan kemudian menyadari bahwa itu harus diterapkan juga untuk 'memelihara ' Anda harus mendasarkan alur kerja baik pada penggabungan, atau pada rebase (atau "git pull --rebase").

Harap ingat bahwa komit yang dipetik atau diubah kembali berbeda dari sudut pandang Git (memiliki pengidentifikasi SHA-1 yang berbeda) dari yang asli, jadi itu berbeda dari komit di repositori jarak jauh. (Rebase biasanya dapat menangani ini, karena memeriksa patch id yaitu perubahan, bukan komit).

Juga di git Anda dapat menggabungkan banyak cabang sekaligus: disebut gurita bergabung . Perhatikan bahwa penggabungan gurita harus berhasil tanpa konflik. Meskipun demikian mungkin bermanfaat.

HTH.

Jakub Narębski
sumber
19
+1 untuk poin yang rebase / memetik ceri sebenarnya "menyalin" komit dan karenanya kehilangan tautan ke komit asli.
studgeek
1
Kami menggunakan cherry-pick dengan cara ini, secara eksklusif untuk memindahkan komit untuk perbaikan bug (mungkin fitur SANGAT KECIL) ke cabang rilis yang ada untuk menyiapkan patch. Fitur yang menjangkau beberapa komit umumnya menjamin masuk ke cabang rilis yang didasarkan dari master.
foxxtrot
3
@foxxtrot: Solusi lain adalah membuat cabang terpisah untuk perbaikan bug, berdasarkan komit tertua yang menunjukkan bug ini, dan menggabungkannya menjadi 'Maint' dan menjadi 'Master' ... meskipun dalam kasus ini Anda perlu tahu bahwa perbaikan bug mengatakan berlaku untuk kedua cabang.
Jakub Narębski
4
@ Yakub Dua perintah yang sangat diperlukan untuk membuat dan menggabungkan cabang perbaikan bug: git blameuntuk menemukan komit yang memperkenalkan bug, dan git branch --containsuntuk menentukan di mana untuk menggabungkan cabang. Dijelaskan lebih rinci dalam posting ini
gcbenison
-10

Rebase dan Cherry-pick adalah satu-satunya cara Anda menjaga riwayat komit tetap bersih. Hindari menggunakan penggabungan dan hindari membuat konflik penggabungan. Jika Anda menggunakan gerrit, atur satu proyek ke Gabung jika perlu dan satu proyek ke mode pilih-ceri dan coba sendiri.

Nagaraj Magadum
sumber
tidak jelas sama sekali bagaimana ini menjawab pertanyaan, mungkin beberapa contoh akan membawa beberapa cahaya.
Adrian Nasui
1
Fakta bahwa sejarah Anda akan terlihat lurus tidak menyiratkan bahwa itu akan lebih mudah untuk dipahami.
nicolimo86
Penggabungan adalah cara biasa untuk memiliki riwayat yang bersih. Cherry-pick dan rebase sebagian besar digunakan untuk situasi di mana Anda harus memodifikasi sejarah. Apa artinya penggabungan harus selalu menjadi pilihan pertama. Karena rebase diubah, bukan apa yang sangat berbahaya ketika Anda bekerja dengan remote dan banyak orang.
Radon8472
Orang ini layak mendapat medali. Dia tahu dia akan terus terpilih, tapi itu jawaban yang tepat. Pujian.
PW Kad
Maaf saya tidak melihat komentar ini sampai sekarang, Silakan coba di lingkungan pengujian Anda sebelum menyimpulkan dan melakukan apa yang berhasil untuk Anda! Saya memiliki sekitar 600 pengembang yang berkontribusi pada banyak cabang produk, saya tidak peduli apa yang dilakukan pengembang di sana, ketika perubahan diajukan untuk integrasi, ia harus dapat memilih cabang pengembangan atau terkadang merilis atau memperbaiki bug cabang. FYI ... Saya menggunakan Gerrit.
Nagaraj Magadum