Dalam git, bagaimana cara membuat versi untuk selusin perpustakaan semuanya bekerja secara paralel

11

Kami sedang mengerjakan proyek, tetapi kami menggunakan kembali banyak kode di antara proyek dan memiliki banyak perpustakaan yang berisi kode umum kami. Saat kami mengimplementasikan proyek baru, kami menemukan lebih banyak cara untuk memfaktorkan kode umum dan memasukkannya ke perpustakaan. Perpustakaan bergantung satu sama lain, dan proyek tergantung pada perpustakaan. Setiap proyek, dan semua perpustakaan yang digunakan dalam proyek itu, perlu menggunakan versi yang sama dari semua perpustakaan yang mereka maksud. Jika kami merilis perangkat lunak, kami harus memperbaiki bug dan mungkin menambahkan fitur baru selama bertahun-tahun, terkadang selama beberapa dekade. Kami memiliki sekitar selusin perpustakaan, perubahan sering kali lebih dari dua, dan beberapa tim bekerja pada beberapa proyek secara paralel, membuat perubahan bersamaan untuk semua perpustakaan ini.

Kami baru saja beralih ke git dan mengatur repositori untuk setiap perpustakaan dan setiap proyek. Kami menggunakan simpanan sebagai repositori umum, melakukan hal-hal baru pada cabang fitur, lalu membuat permintaan tarik dan menggabungkannya hanya setelah ditinjau.

Banyak masalah yang harus kita tangani dalam proyek mengharuskan kita melakukan perubahan di beberapa perpustakaan dan kode spesifik proyek. Ini sering termasuk perubahan antarmuka perpustakaan, beberapa di antaranya tidak kompatibel. (Jika menurut Anda ini terdengar mencurigakan: Kami berinteraksi dengan perangkat keras, dan menyembunyikan perangkat keras tertentu di belakang antarmuka umum. Hampir setiap kali kami mengintegrasikan beberapa perangkat keras vendor lain, kami mengalami kasus-kasus yang tidak diantisipasi oleh antarmuka kami saat ini, sehingga harus disempurnakan.) Untuk misalnya, bayangkan sebuah proyek P1menggunakan perpustakaan L1, L2dan L3. L1juga menggunakan L2dan L3, dan L2menggunakan L3juga. Grafik ketergantungan terlihat seperti ini:

   <-------L1<--+
P1 <----+  ^    |
   <-+  |  |    |
     |  +--L2   |
     |     ^    |
     |     |    |
     +-----L3---+

Sekarang bayangkan sebuah fitur untuk proyek ini membutuhkan perubahan P1dan L3yang mengubah antarmuka L3. Sekarang tambahkan proyek P2dan P3ke dalam campuran, yang juga merujuk ke perpustakaan ini. Kami tidak mampu mengalihkan semuanya ke antarmuka baru, menjalankan semua tes, dan menggunakan perangkat lunak baru. Jadi apa alternatifnya?

  1. mengimplementasikan antarmuka baru di L3
  2. buat permintaan tarik L3dan tunggu ulasannya
  3. gabungkan perubahan
  4. buat rilis baru L3
  5. mulailah bekerja pada fitur P1dengan membuatnya merujuk ke L3rilis baru, kemudian mengimplementasikan fitur pada P1cabang fitur
  6. buat permintaan tarik, periksa ini, dan bergabung

(Saya hanya memperhatikan bahwa saya lupa untuk beralih L1dan L2ke rilis baru. Dan saya bahkan tidak tahu di mana harus memasukkan ini, karena itu harus dilakukan bersamaan dengan P1...)

Ini adalah proses yang membosankan, rawan kesalahan, dan sangat panjang untuk mengimplementasikan fitur ini, perlu tinjauan independen (yang membuatnya jauh lebih sulit untuk ditinjau), tidak berskala sama sekali, dan cenderung membuat kami keluar dari bisnis karena kami terjebak dalam proses kami tidak pernah menyelesaikan apa pun.

Tetapi bagaimana kita menggunakan percabangan dan penandaan untuk menciptakan proses yang memungkinkan kita untuk mengimplementasikan fitur-fitur baru dalam proyek-proyek baru tanpa terlalu banyak overhead?

sbi
sumber
1
Mengubah alat Anda tidak akan terlalu memengaruhi proses yang Anda lakukan. Jadi, bagaimana Anda menangani masalah ini sebelum beralih ke git?
Bart van Ingen Schenau
Apakah mungkin untuk hanya menambahkan metode baru ke antarmuka tanpa merusak yang sudah ada ketika perpustakaan terlalu banyak bergantung padanya? Biasanya itu bukan ide terbaik, tetapi setidaknya itu akan membuat Anda "melanjutkan" menerapkan fitur baru dan Anda dapat benar-benar mencela metode lama setiap kali ada waktu luang. Atau apakah antarmuka ini terlalu stateful untuk "antarmuka paralel" seperti itu tidak berfungsi?
Ixrec
1
@ Isrec: Saya diberitahu bahwa "ini bukan cara git" dalam melakukan sesuatu. Semua orang menggunakan repositori individual untuk proyek-proyek individual, jadi diputuskan kami juga melakukannya.
sbi
2
Saya berpendapat mereka bukan proyek terpisah jika mereka sering harus diubah bersama-sama. Batas antara "proyek" harus selalu memiliki semacam jaminan kompatibilitas mundur jangka panjang.
Ixrec
1
@Ixrec: Mengintegrasikan lebih banyak perangkat keras mirip dengan kode porting ke lebih banyak platform: semakin banyak Anda melakukan ini, semakin sedikit yang perlu Anda ubah untuk perangkat keras / platform lainnya. Jadi dalam jangka panjang, kode akan stabil. Namun, saat ini kita perlu menemukan proses yang memungkinkan kita untuk tinggal di pasar cukup lama untuk sampai ke sana.
sbi

Jawaban:

5

Agak mengeluarkan yang jelas di sini, tapi mungkin layak untuk menyebutkannya.

Biasanya, repositori git dirancang khusus per lib / proyek karena cenderung independen. Anda memperbarui proyek Anda, dan tidak peduli sisanya. Proyek-proyek lain tergantung padanya hanya akan memperbarui lib mereka kapan saja mereka mau.

Namun, kasing Anda tampaknya sangat tergantung pada komponen yang berkorelasi, sehingga satu fitur biasanya memengaruhi banyak di antaranya. Dan keseluruhannya harus dikemas sebagai bundel. Karena mengimplementasikan fitur / perubahan / bug sering mengharuskan untuk mengadaptasi banyak pustaka / proyek yang berbeda sekaligus, mungkin masuk akal untuk menempatkan semuanya dalam repo yang sama.

Ada kelebihan / kekurangan kuat untuk ini.

Keuntungan:

  • Ketertelusuran: cabang menunjukkan segala sesuatu berubah di setiap proyek / lib terkait dengan fitur / bug ini.
  • Bundling: cukup pilih tag, dan Anda akan mendapatkan semua sumber dengan benar.

Kekurangan:

  • Penggabungan: ... terkadang sudah sulit dengan satu proyek. Dengan berbagai tim bekerja di cabang bersama, bersiaplah untuk bersiap menghadapi dampak.
  • Faktor "oops" yang berbahaya: jika satu karyawan mengacaukan repositori dengan membuat kesalahan, itu mungkin berdampak pada semua proyek & tim.

Terserah Anda untuk mengetahui apakah harganya sepadan dengan manfaatnya.

EDIT:

Ini akan bekerja seperti ini:

  • Fitur X harus diimplementasikan
  • Buat cabang feature_x
  • Semua pengembang yang terlibat bekerja pada cabang ini dan mengerjakannya dengan kejam, mungkin dalam direktori khusus yang berkaitan dengan proyek / lib mereka
  • Setelah selesai, tinjau, uji, bungkus, apa pun
  • Gabungkan kembali di master ... dan ini mungkin bagian yang sulit karena sementara itu feature_ydan feature_zmungkin telah ditambahkan juga. Itu menjadi gabungan "lintas tim". Inilah sebabnya mengapa ini merupakan kelemahan serius.

hanya untuk catatan: Saya pikir ini dalam banyak kasus adalah ide yang buruk dan harus dilakukan dengan hati-hati karena kelemahan gabungan biasanya lebih tinggi daripada yang Anda dapatkan melalui manajemen ketergantungan / pelacakan fitur yang tepat.

dagnelies
sumber
Terima kasih, kami memang sedang melihat ini. Yang tidak saya mengerti dari sudut pandang ini adalah bagaimana kita melakukan percabangan dengan git. Dalam SVN, percabangan berarti menyalin subtree (dalam repositori) ke tempat lain (dalam repositori). Dengan ini, mudah untuk membuat cabang dari subtree apa pun di repo Anda, jadi jika Anda memiliki banyak proyek di sana, Anda dapat bercabang masing-masing secara individual. Apakah ada sesuatu seperti ini di git, atau apakah kita akan selalu dapat melakukan repo secara keseluruhan?
sbi
@ sbi: Anda akan menaburkan seluruh repo. Anda tidak dapat bekerja dengan sub-cabang di cabang-cabang yang berbeda, yang akan mengalahkan poin dalam kasus Anda. Git tidak akan "menyalin" apa pun, itu hanya akan melacak perubahan di cabang yang sedang Anda kerjakan.
dagnelies
Jadi ini mengharuskan seseorang membuat cabang fitur untuk satu pustaka untuk juga menggabungkan yang lainnya saat menggabungkan atau mem-rebasing. Ini adalah kelemahan nyata. (BTW, SVN juga hanya pernah melakukan salinan malas.)
sbi
@sbi: lihat sunting
dagnelies
1
Nah, saat ini kebanyakan dari kita tidak nyaman. :-/Terlebih lagi, bahkan mereka yang (dan yang mendorong untuk pindah ke git), tidak tahu bagaimana membuat proses pengembangan kami cocok dengan git. Mendesah. Saya khawatir, ini akan menjadi bulan-bulan yang sulit, sampai segalanya menjadi lebih lancar. Bagaimanapun, terima kasih, jawaban Anda adalah yang paling membantu hanya sejauh ini.
sbi
4

Solusi yang Anda cari adalah alat manajemen ketergantungan yang berkoordinasi dengan submodules git

Alat-alat seperti:

  • Maven
  • Semut
  • Komposer

Anda dapat menggunakan alat-alat itu untuk menentukan dependensi suatu proyek.

Anda dapat meminta submodule setidaknya versi > 2.xx atau menunjukkan berbagai versi yang kompatibel = 2.2. * Atau kurang dari versi tertentu <2.2.3

Setiap kali Anda merilis versi baru dari salah satu paket, Anda dapat menandainya dengan nomor versi, dengan cara itu Anda dapat menarik versi kode yang spesifik ke semua proyek lain.

Patrick
sumber
Tetapi manajemen ketergantungan bukan masalah kita, ini diselesaikan. Kami saat ini secara teratur melakukan perubahan di banyak perpustakaan dan perlu meminimalkan overhead untuk membuat versi baru sambil mempertahankan rilis proyek yang stabil. Jawaban Anda sepertinya tidak memberikan solusi untuk ini.
sbi
@ sbi Ini akan mengatur overhead untuk membuat versi baru dan mempertahankan rilis proyek yang stabil. Karena Anda dapat menentukan bahwa proyek x bergantung pada proyek y versi 2.1.1, Anda dapat membuat versi baru proyek y yang tidak akan memengaruhi proyek x.
Patrick
Sekali lagi, menyatakan dependensi bukanlah masalah kita. Kita sudah bisa melakukan ini. Masalahnya adalah bagaimana mengelola perubahan yang melintasi beberapa proyek / perpustakaan secara efisien. Jawaban Anda gagal menjelaskan ini.
sbi
@sbi: jadi apa sebenarnya masalah Anda? Anda membuat perubahan, menabrak versi, memperbarui dependensi jika diperlukan, dan voila. Apa yang Anda jelaskan di posting awal adalah tipikal & pakar. barang. Setiap distribusi didasarkan pada lib versi yang didefinisikan dengan jelas. Bagaimana itu bisa lebih jelas?
dagnelies
@arnaud: Waktu penyelesaian untuk proses seperti itu untuk (saat ini agak umum) perubahan memotong tiga lapisan atau lebih akan membunuh kita. Saya pikir pertanyaan saya menggambarkan hal itu.
sbi
0

Submodules

Anda harus mencoba untuk mendapatkan submodula , seperti yang disarankan dalam satu komentar.

Ketika proyek P1merujuk pada tiga submodul L1, L2dan L3, ia sebenarnya menyimpan referensi ke komitmen tertentu di ketiga repositori: itu adalah versi kerja dari masing-masing perpustakaan untuk proyek itu .

Jadi beberapa proyek dapat bekerja dengan beberapa submodul: P1mungkin merujuk ke versi lama perpustakaan L1sementara proyek P2menggunakan versi baru.

Apa yang terjadi ketika Anda memberikan versi baru L3?

  • mengimplementasikan antarmuka baru di L3
  • komit, uji , buat permintaan tarik, ulas, gabung, ... (Anda tidak bisa menghindari ini)
  • memastikan L2bekerja dengan L3, komit, ...
  • memastikan L1bekerja dengan yang baru L2, ...
  • memastikan P1bekerja dengan versi baru semua perpustakaan:
    • di dalam P1copy pekerjaan lokal dari L1, L2dan L3, perubahan yang Anda minati.
    • mengkomit perubahan, git add L1 L2 L3untuk mengkomit referensi baru ke modul
    • tarik permintaan P1, uji, tinjau, tarik permintaan, gabungkan ...

Metodologi

Ini adalah proses yang membosankan, rawan kesalahan, dan sangat panjang untuk mengimplementasikan fitur ini, perlu tinjauan independen (yang membuatnya jauh lebih sulit untuk ditinjau), tidak berskala sama sekali, dan cenderung membuat kami keluar dari bisnis karena kami terjebak dalam proses kami tidak pernah menyelesaikan apa pun.

Ya, ini membutuhkan ulasan independen, karena Anda mengubah:

  • Perpustakaan
  • perpustakaan yang bergantung padanya
  • proyek yang bergantung pada banyak pustaka

Apakah Anda akan keluar dari bisnis karena Anda memberikan omong kosong? (Mungkin tidak, sebenarnya). Jika ya, maka Anda perlu melakukan tes dan meninjau perubahan.

Dengan alat git yang sesuai (datar gitk), Anda dapat dengan mudah melihat versi perpustakaan mana yang digunakan setiap proyek, dan Anda dapat memperbaruinya secara mandiri sesuai dengan kebutuhan Anda. Submodules sempurna untuk situasi Anda dan tidak akan memperlambat proses Anda.

Mungkin Anda dapat menemukan cara untuk mengotomatisasi bagian dari proses ini, tetapi sebagian besar langkah di atas membutuhkan otak manusia. Cara paling efektif untuk menghemat waktu adalah memastikan perpustakaan dan proyek Anda mudah berkembang. Jika basis kode Anda dapat menangani persyaratan baru dengan anggun, maka ulasan kode akan lebih sederhana dan menyita sedikit waktu Anda.

(Edit) hal lain yang mungkin membantu Anda adalah mengelompokkan ulasan kode terkait. Anda melakukan semua perubahan dan menunggu sampai Anda menyebarkan perubahan itu ke semua perpustakaan dan proyek yang menggunakannya sebelum menghentikan permintaan tarik (atau sebelum Anda mengurusnya). Anda akhirnya melakukan ulasan yang lebih besar untuk seluruh rantai ketergantungan. Mungkin ini dapat membantu Anda menghemat waktu jika setiap perubahan lokal kecil.

coredump
sumber
Anda menjelaskan cara mengatasi masalah ketergantungan (yang, seperti telah saya katakan sebelumnya, telah kami atasi) dan meniadakan masalah yang kami alami. Mengapa kamu repot-repot? (FWIW, kami menulis perangkat lunak yang menggerakkan pembangkit listrik. Kode yang bersih, aman, dan ditinjau secara menyeluruh adalah fitur utama.)
sbi
@ sbi Apa itu submodula jika bukan kasus percabangan dan penandaan khusus? Anda pikir submodul adalah tentang manajemen dependensi, karena mereka juga melacak dependensi. Tapi tentu, tolong buat kembali submodules dengan tag jika Anda mau, saya tidak keberatan. Saya tidak mengerti masalah Anda: jika kode yang ditinjau adalah fitur utama, Anda harus menganggarkan waktu untuk ulasan. Anda tidak macet, Anda pergi secepat mungkin dengan kendala yang ada pada Anda.
coredump
Ulasan sangat penting bagi kami. Itulah salah satu alasan kami khawatir tentang masalah (dan ulasannya) dipecah menjadi beberapa ulasan untuk beberapa perubahan di beberapa repositori. Ditambah lagi, kami tidak ingin terjebak dalam administrasi kami sampai mati karena satu masalah adalah bahwa kami lebih suka menghabiskan waktu menulis dan meninjau kode. Re submodules: sejauh ini, satu-satunya hal yang saya dengar tentang mereka adalah "jangan repot-repot, ini bukan cara git". Nah, mengingat persyaratan kami tampaknya sangat unik, mungkin kita harus meninjau kembali keputusan ini ...
sbi
0

Jadi yang saya mengerti adalah Anda untuk P1 Anda ingin mengubah antarmuka L3 tetapi Anda ingin P2 dan P3 lainnya yang bergantung pada antarmuka L3 untuk segera berubah. Ini adalah kasus khas kompatibilitas mundur. Ada artikel bagus tentang Kompatibilitas Mundur Preservasi ini

Ada beberapa cara untuk menyelesaikannya:

  • Anda harus membuat antarmuka baru setiap kali dapat memperpanjang antarmuka lama.

ATAU

  • Jika Anda ingin menghentikan antarmuka lama setelah beberapa waktu, Anda dapat memiliki beberapa versi antarmuka dan begitu semua proyek yang bergantung pindah Anda menghapus antarmuka yang lebih lama.
Uday Shankar
sumber
1
Tidak, kompatibilitas mundur dipastikan melalui cabang rilis dan bukan masalah kami. Masalahnya adalah bahwa kita duduk di basis kode yang saat ini berubah dengan cepat, yang basah ingin memisahkan ke perpustakaan sekarang, terlepas dari kenyataan bahwa antarmuka masih dalam fase di mana mereka sering berubah. Saya tahu bagaimana mengelola binatang seperti itu di SVN, tetapi tidak tahu bagaimana melakukannya di git tanpa tenggelam dalam administrasi.
sbi
0

Jika saya memperbaiki masalah Anda:

  • Anda memiliki 4 modul yang saling terkait, P1 dan L1 hingga L3
  • Anda perlu melakukan perubahan ke P1 yang pada akhirnya akan mempengaruhi L1 ke L3
  • itu dianggap sebagai kegagalan proses jika Anda harus mengubah semua 4 bersama-sama
  • itu dianggap sebagai kegagalan proses jika Anda harus mengubah semuanya 1 per 1.
  • itu dianggap sebagai kegagalan proses jika Anda harus mengidentifikasi terlebih dahulu potongan di mana perubahan harus dilakukan.

Jadi tujuannya adalah Anda dapat melakukan P1 dan L1 dalam sekali jalan, dan kemudian sebulan kemudian melakukan L2 dan L3 di tempat lain.

Di dunia Java, ini sepele, dan mungkin cara standar untuk bekerja:

  • semuanya berjalan dalam satu repositori tanpa menggunakan percabangan yang relevan
  • modul dikompilasi + dihubungkan bersama oleh pakar berdasarkan nomor versi, bukan fakta bahwa semuanya ada di pohon direktori yang sama.

Jadi, Anda dapat memiliki kode pada disk lokal Anda untuk L3 yang tidak dapat dikompilasi jika kompilasi terhadap salinan P1 di direktori lain pada disk Anda; untungnya itu tidak terjadi. Java dapat langsung melakukan ini karena mengkompilasi / menautkan dongeng terjadi pada file jar yang dikompilasi, bukan kode sumber.

Saya tidak mengetahui solusi yang sudah ada sebelumnya yang banyak digunakan untuk masalah ini untuk dunia C / C ++, dan saya membayangkan Anda tidak ingin beralih bahasa. Tetapi sesuatu dapat dengan mudah diretas bersama dengan membuat file yang melakukan hal yang sama:

  • pustaka + header terinstal ke direktori yang dikenal dengan nomor versi tertanam
  • jalur kompiler yang diubah per modul ke direktori untuk nomor versi yang sesuai

Anda bahkan dapat menggunakan dukungan C / C ++ di pakar , meskipun sebagian besar pengembang C akan melihat Anda aneh jika Anda melakukannya ...

soru
sumber
"Ini dianggap sebagai kegagalan proses jika Anda harus mengubah semua 4 bersama" . Sebenarnya tidak. Sebenarnya, ini adalah persis apa yang kami lakukan menggunakan SVN.
sbi
Dalam hal ini maka saya kira tidak ada masalah dengan hanya menempatkan semua proyek di repositori.
soru
Kami sekarang mengevaluasi menempatkan perpustakaan ke dalam hanya dua repositori. Itu masih lebih dari satu, tetapi jauh lebih sedikit dari "satu untuk setiap proyek", dan perpustakaan dapat dibagi menjadi dua kelompok. Terima kasih atas masukan Anda!
sbi
PS: "Saya bayangkan Anda tidak ingin berganti bahasa." Ini adalah barang yang disematkan. :)
sbi
-1

Ada solusi sederhana: potong cabang rilis di seluruh repositori, gabungkan semua perbaikan ke semua rilis yang dikirimkan secara aktif (mudah dalam kasus yang jelas harus dimungkinkan di git).

Semua alternatif akan menciptakan kekacauan yang mengerikan seiring waktu dan dengan pertumbuhan proyek.

zzz777
sumber
Bisakah Anda jelaskan? Saya tidak yakin apa yang Anda sarankan.
sbi
Dalam kasus yang jelas, Anda menentukan titik cabang sebagai cabang dasar dan cap waktu. Anda memiliki hierarki berikut: cabang dasar -> rilis-pengembangan-cabang -> cabang pengembangan-swasta. Semua pengembangan dilakukan pada private-branch dan kemudian digabungkan ke dalam hierarki. Cabang rilis pelanggan diputuskan cabang rilis-pengembangan-. Saya tidak begitu terbiasa dengan git tetapi tampaknya hal yang paling dekat untuk membersihkan kasus di antara sistem kontrol sumber gratis.
zzz777
Membaca dengan seksama pertanyaan saya seharusnya menunjukkan kepada Anda bahwa kami memiliki masalah dengan overhead yang terlibat dalam menyebarkan perubahan di antara repositori. Ini tidak ada hubungannya dengan jawaban Anda.
sbi
@sbi Maaf saya salah mengerti pertanyaan Anda. Dan saya khawatir Anda akan menghadapi kekacauan yang mengerikan cepat atau lambat.
zzz777