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 P1
menggunakan perpustakaan L1
, L2
dan L3
. L1
juga menggunakan L2
dan L3
, dan L2
menggunakan L3
juga. Grafik ketergantungan terlihat seperti ini:
<-------L1<--+
P1 <----+ ^ |
<-+ | | |
| +--L2 |
| ^ |
| | |
+-----L3---+
Sekarang bayangkan sebuah fitur untuk proyek ini membutuhkan perubahan P1
dan L3
yang mengubah antarmuka L3
. Sekarang tambahkan proyek P2
dan P3
ke 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?
- mengimplementasikan antarmuka baru di
L3
- buat permintaan tarik
L3
dan tunggu ulasannya - gabungkan perubahan
- buat rilis baru
L3
- mulailah bekerja pada fitur
P1
dengan membuatnya merujuk keL3
rilis baru, kemudian mengimplementasikan fitur padaP1
cabang fitur - buat permintaan tarik, periksa ini, dan bergabung
(Saya hanya memperhatikan bahwa saya lupa untuk beralih L1
dan L2
ke 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?
Jawaban:
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:
Kekurangan:
Terserah Anda untuk mengetahui apakah harganya sepadan dengan manfaatnya.
EDIT:
Ini akan bekerja seperti ini:
feature_x
feature_y
danfeature_z
mungkin 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.
sumber
:-/
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.Solusi yang Anda cari adalah alat manajemen ketergantungan yang berkoordinasi dengan submodules git
Alat-alat seperti:
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.
sumber
Submodules
Anda harus mencoba untuk mendapatkan submodula , seperti yang disarankan dalam satu komentar.
Ketika proyek
P1
merujuk pada tiga submodulL1
,L2
danL3
, 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:
P1
mungkin merujuk ke versi lama perpustakaanL1
sementara proyekP2
menggunakan versi baru.Apa yang terjadi ketika Anda memberikan versi baru
L3
?L3
L2
bekerja denganL3
, komit, ...L1
bekerja dengan yang baruL2
, ...P1
bekerja dengan versi baru semua perpustakaan:P1
copy pekerjaan lokal dariL1
,L2
danL3
, perubahan yang Anda minati.git add L1 L2 L3
untuk mengkomit referensi baru ke modulP1
, uji, tinjau, tarik permintaan, gabungkan ...Metodologi
Ya, ini membutuhkan ulasan independen, karena Anda mengubah:
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.
sumber
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:
ATAU
sumber
Jika saya memperbaiki masalah Anda:
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:
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:
Anda bahkan dapat menggunakan dukungan C / C ++ di pakar , meskipun sebagian besar pengembang C akan melihat Anda aneh jika Anda melakukannya ...
sumber
:)
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.
sumber