Gabungkan perbaikan bug dari trunk di cabang lama

9

Kami sekarang sedang dalam proses beralih dari svn ke git (setelah satu tahun dihabiskan untuk meyakinkan orang, ya!) Di perusahaan saya.

Sejauh ini, ini semua menjadi lebih baik tetapi ada satu hal kecil yang saat ini kami miliki dalam alur kerja kami sehingga saya tidak dapat menemukan padanan yang baik juga.

Saat ini, semua pengembang kami bekerja secara master. Setiap triwulan, kami cabang master ke cabang Xx, yang nantinya akan menjadi rilis terbaru kami. Ini berarti repo svn kami terlihat seperti ini:

  • bagasi
  • ranting
    • 3.8
    • 4.1
    • 4.2
    • ...

Kami tidak benar-benar menggunakan tag.

Sesekali, ada perbaikan bug mendesak yang ditemukan.

Cara saat ini bagi kita untuk melakukannya adalah:

  • Perbaiki di master
  • SVN menggabungkan kisaran komit yang relevan kembali ke cabang yang relevan (Mungkin rilis terbaru kami, mungkin lebih).

Kami berada di industri luar angkasa, sehingga cabang kami berumur panjang dan proses peningkatan pelanggan agak lama, itulah sebabnya kami telah bekerja seperti itu sejauh ini.

Sekarang, bagaimana bisa setara dengan git?

Sejauh ini, saya telah mencoba untuk memperbaiki bug di cabang yang dihasilkan dari master, dan kemudian menggabungkan cabang ini kembali di master dan di 4.3 (misalnya). Masalahnya, cabang perbaikan terbaru berisi sejarah master, dan semua komit antara master dan 4.3 juga digabungkan, yang tidak kami inginkan.

Hal-hal yang dapat saya pikirkan sejauh ini:

  • Saya telah melihat metode Git Workflow yang sangat sukses , dan solusi mereka adalah untuk memperbaiki bug di cabang rilis dan menggabungkannya kembali, bukan sebaliknya. Ini bisa berfungsi dalam kasus kami, tetapi akan agak rumit karena kami harus sudah tahu cabang tertua yang ingin kami perbaiki bug sebelum benar-benar memperbaiki bug.
  • Solusi lain adalah memperbaiki di master, dan kemudian cherry memilih commit (seperti yang kita lakukan untuk penggabungan svn hari ini). Yang menjengkelkan di sini adalah bahwa dalam kasus ini kita kehilangan sejarah tentang apa yang telah digabungkan kembali ke mana, karena pilihan ceri terlihat seperti komitmen baru dan kita kehilangan hubungan.

Jadi apa cara "baik" untuk melakukannya? Haruskah kita memperbaiki komitmen dalam sejarah, atau memilih cherry dan secara manual melacak apa yang telah digabungkan, atau bahkan sesuatu yang lain?

Jika memiliki sedikit pengalaman produksi dengan git, maka saya yakin saya mungkin melewatkan sesuatu.

jlengrand
sumber

Jawaban:

9

Git Flow mengasumsikan Anda hanya memiliki satu rilis yang didukung, dengan mastercabang selalu menunjuk ke rilis terbaru. Karena Anda mendukung beberapa rilis secara bersamaan, Anda tidak dapat menyalin alur kerja itu 1: 1. Aliran Git Nvie adalah contoh yang sangat bagus dari strategi percabangan, tetapi Anda harus menyesuaikannya dengan kebutuhan Anda. Yang paling penting, Anda akan memiliki beberapa cabang rilis aktif.

Ketika Anda mengidentifikasi bug, Anda harus melakukan beberapa pengujian untuk menentukan semua versi yang terpengaruh. Tidak cukup untuk menulis perbaikan terlebih dahulu, kemudian menggabungkannya kembali ke cabang rilis sebagai perbaikan terbaru. Biasanya, Anda akan berakhir dengan beberapa versi berkelanjutan dari versi yang terpengaruh. Versi yang sangat lama mungkin tidak mengandung bug, versi yang lebih baru mungkin mendapatkan bug itu diperbaiki secara tidak sengaja. Anda perlu memverifikasi bug pada setiap versi sehingga Anda dapat memverifikasi bahwa bug tersebut benar-benar hilang setelah perbaikan. Jika Anda dapat mengekspresikan bug sebagai testcase otomatis, cukup mudah untuk menemukan komit yang bermasalah via git bisect, atau menjalankan tes untuk setiap rilis:

for release in 3.8 4.1 4.2
do
  git checkout $release
  if ./testcase >release-$release.log
  then echo "$release ok"
  else echo "$release AFFECTED"
  fi
done

Sekarang, Anda biasa menulis perbaikan di trunk/ master. Ini bermasalah karena bagian kereta mungkin telah berubah di antara versi, jadi tambalan biasanya tidak berlaku untuk versi yang lebih lama. Secara khusus, kode dalam mastermungkin bergantung pada fitur apa pun yang tersedia di master, yang mungkin tidak ada dalam versi yang lebih lama. Oleh karena itu masuk akal bahwa Git melakukan referensi seluruh sejarahnya, bukan hanya set perubahan. Saat menggabungkan kembali, itu akan menarik semua sejarah yang bergantung padanya.

Menggunakan cherry-pickatau rebasemengabaikan riwayat ini, dan mencatat komitmen baru dengan set perubahan yang sama, tetapi riwayat yang berbeda. Seperti yang ditunjukkan, ini tidak akan berfungsi jika basis kode Anda telah menyimpang.

Solusi "benar" adalah menulis perbaikan sebagai perbaikan terbaru pada rilis tertua yang terpengaruh. Kemudian, Anda menggabungkan rilis terlama ke rilis tertua kedua. Biasanya, rilis yang lebih baru akan berisi semua komit dari rilis yang lebih lama, jadi ini OK. Jika ada yang berubah, Anda sekarang memiliki kesempatan untuk menyelesaikan konflik gabungan secara manual. Kemudian Anda terus menggabungkan setiap rilis ke rilis berikutnya yang lebih muda sampai Anda selesai. Ini mempertahankan sejarah yang tepat dan menghindari banyak pekerjaan yang tidak perlu, sementara hanya membutuhkan upaya yang harus dikeluarkan. Secara khusus, penggabungan bertahap ini membuat Anda lebih dekat dengan status perkembangan saat ini dalam langkah-langkah kecil.

Sebagai diagram:

| o normal commit |
| x hotfix        |
| ⇘ merging       |

3.8 --o-----------------x
       \                 ⇘
4.1     o--o--o-----------x'
               \           ⇘
4.2             o--o--o-----x''
                       \     ⇘
develop                 o--o--x'''--o--o
amon
sumber
2
Untuk kelengkapan, katakanlah tes itu sedikit salah dan versi 3.7 memiliki bug yang sama (katakanlah, itu hanya terjadi pada kasus tepi di 3,7, tetapi terjadi dalam kasus yang lebih mudah diuji dalam 3,8+), tetapi hanya ditemukan setelah memperbaiki digabung seperti ini. Apakah Anda hanya memilih ceri pada saat itu?
Izkata
2
@Izkata ya, pada saat itu tidak mungkin lagi berpura-pura bahwa ada semacam sejarah yang masuk akal, jadi memetik ceri adalah cara yang baik untuk menerapkan perubahan pada rilis yang lebih lama. Namun, ini menyiratkan bahwa cabang rilis telah menyimpang, dan rilis yang lebih baru tidak lagi berisi semua komitmen dari rilis yang lebih lama. Oleh karena itu, kita harus melakukan rantai penggabungan lagi dari rilis yang kita ubah hingga cabang pengembangan. Namun, selama penggabungan pertama, kami dapat membuang perubahan yang dipilih karena kami telah menerapkan perbaikan pada rilis yang lebih baru.
amon
Terima kasih atas jawaban Anda pada @amon. Jawaban Anda sangat lengkap, dan pergi ke arah yang saya lihat sudah, jadi itu bagus untuk memiliki validasi. Kami akan mengambil persyaratan industri kami sendiri dan mengadaptasi pendekatan aliran git ke sesuatu yang lebih cocok bagi kami. Terima kasih lagi!
jlengrand