Penjelasan Aliran Git yang Ditingkatkan
Diterbitkan: 2022-03-11Secara tidak sengaja menyebabkan kerusakan dengan Git bisa sangat mudah. Namun, cara terbaik untuk menggunakan Git akan selalu kontroversial.
Itu karena Git sendiri hanya merinci operasi percabangan dasar, yang membiarkan pola penggunaannya—yaitu, model percabangan—masalah pendapat pengguna. Model percabangan Git berjanji untuk meringankan rasa sakit dengan mengatur kekacauan yang pasti muncul saat pengembang perangkat lunak membuat perubahan pada basis kode mereka.
Seperti banyak pengembang, Anda menginginkan sesuatu yang "berfungsi" sehingga Anda dapat melanjutkan pengembangan perangkat lunak yang sebenarnya. Jadi, Anda mengambil Git flow , model percabangan yang sering direkomendasikan kepada pengguna Git. Mungkin Anda sudah terbiasa dengan logika aliran Git pada awalnya, sampai Anda menemukan beberapa hambatan dalam praktiknya. Atau mungkin aliran Git sepertinya tidak cukup cocok untuk Anda adopsi. Lagi pula, ada banyak variabel yang berperan, dan tidak ada model percabangan tunggal yang akan bekerja dengan baik di setiap situasi.
Kabar baik! Variasi dari model aliran Git klasik, aliran Git yang disempurnakan menyederhanakan manuver yang lebih umum dari alur kerja aliran Git sambil tetap mempertahankan keunggulan utama.
Kemegahan dan Kesengsaraan Model Aliran Git Klasik
Saya telah menjadi pendukung kuat aliran Git sejak saya menemukan keunggulannya saat mengembangkan produk yang berkembang dalam peningkatan nilai yang signifikan (dengan kata lain, releases ).
Peningkatan nilai yang signifikan membutuhkan banyak waktu untuk diselesaikan, seperti sprint dua minggu lebih yang biasanya digunakan dalam pengembangan berbasis Scrum. Jika tim pengembangan telah dikerahkan ke produksi, mungkin ada masalah jika cakupan rilis berikutnya terakumulasi di tempat yang sama di mana kode produksi berada—misalnya, di cabang utama repo Git yang mereka gunakan.
Sementara produk masih dalam tahap pengembangan awal—yaitu, tidak ada produksi dan tidak ada pengguna produk yang sebenarnya—tidak apa-apa bagi tim untuk menyimpan semuanya di dalam cabang utama. Faktanya, ini lebih dari cukup: Strategi ini memungkinkan laju perkembangan tercepat tanpa banyak upacara. Tetapi banyak hal berubah dalam lingkungan produksi; kemudian, orang-orang nyata mulai mengandalkan produk untuk menjadi stabil.
Misalnya, jika ada bug kritis dalam produksi yang perlu segera diperbaiki, akan menjadi bencana besar bagi tim pengembangan jika harus memutar kembali semua pekerjaan yang diperoleh di cabang utama sejauh ini hanya untuk menerapkan perbaikan. Dan menerapkan kode tanpa pengujian yang tepat—apakah kode tersebut dianggap setengah matang atau dikembangkan dengan baik—jelas bukan pilihan.
Di situlah model percabangan bersinar, termasuk aliran Git. Setiap model percabangan yang canggih harus menjawab pertanyaan tentang cara mengisolasi rilis berikutnya dari versi sistem yang saat ini digunakan oleh orang-orang, cara memperbarui versi itu dengan rilis berikutnya, dan cara memperkenalkan perbaikan terbaru dari setiap bug kritis ke versi saat ini.
Proses aliran Git membahas skenario mendasar ini dengan memisahkan "main" (cabang produksi atau "versi saat ini") dan "develop" (cabang pengembangan atau "rilis berikutnya") dan menyediakan semua aturan tentang penggunaan cabang fitur/rilis/perbaikan terbaru . Ini secara efektif memecahkan banyak sakit kepala dari alur kerja pengembangan produk berbasis rilis.
Tetapi bahkan dengan proyek yang sangat cocok dengan model aliran Git klasik, saya telah mengalami masalah khas yang dapat ditimbulkannya:
- Aliran Git rumit, dengan dua cabang berumur panjang, tiga jenis cabang sementara, dan aturan ketat tentang bagaimana cabang berhubungan satu sama lain. Kompleksitas seperti itu membuat kesalahan lebih mungkin terjadi dan meningkatkan upaya yang diperlukan untuk memperbaikinya.
- Cabang rilis dan perbaikan terbaru memerlukan "penggabungan ganda"—sekali menjadi utama, lalu menjadi berkembang. Terkadang Anda bisa lupa melakukan keduanya. Anda dapat membuat percabangan aliran Git lebih mudah dengan skrip atau plugin klien GUI VCS, tetapi Anda harus mengaturnya terlebih dahulu untuk setiap mesin dari setiap pengembang yang terlibat dalam proyek tertentu.
- Dalam alur kerja CI/CD, Anda biasanya berakhir dengan dua build final untuk rilis—satu dari komit terbaru dari cabang rilis itu sendiri dan satu lagi dari komit gabungan ke main. Sebenarnya, Anda harus menggunakan yang utama, tetapi keduanya biasanya identik, menciptakan potensi kebingungan.
Masukkan "Aliran Git yang Ditingkatkan"
Pertama kali saya menggunakan aliran Git yang ditingkatkan adalah pada proyek sumber tertutup yang ramah lingkungan. Saya bekerja dengan satu pengembang lain, dan kami telah mengerjakan proyek dengan berkomitmen langsung ke cabang utama.
Catatan: Hingga rilis publik pertama suatu produk, sangat masuk akal untuk melakukan semua perubahan secara langsung ke cabang utama—bahkan jika Anda adalah pendukung aliran Git—demi kecepatan dan kesederhanaan alur kerja pengembangan. Karena belum ada produksi, tidak ada kemungkinan bug produksi yang perlu diperbaiki tim secepatnya. Oleh karena itu, melakukan semua keajaiban percabangan yang disiratkan oleh aliran Git klasik terlalu berlebihan pada tahap ini.
Kemudian kami mendekati rilis awal dan kami sepakat bahwa, di luar titik itu, kami tidak akan merasa nyaman lagi dengan melakukan langsung ke cabang utama. Kami telah bergerak cukup cepat, dan prioritas bisnis tidak meninggalkan banyak ruang untuk membangun proses pengembangan yang kokoh—yakni, proses dengan pengujian otomatis yang cukup untuk memberi kami keyakinan bahwa cabang utama kami tetap dalam keadaan siap rilis.
Tampaknya menjadi kasus yang valid untuk model aliran Git klasik. Dengan cabang utama dan pengembangan yang terpisah dan waktu yang cukup antara peningkatan nilai yang signifikan, ada keyakinan bahwa sebagian besar QA manual akan memberikan hasil yang cukup baik. Ketika saya menganjurkan aliran Git, rekan saya menyarankan sesuatu yang serupa, tetapi dengan beberapa perbedaan utama.
Pada awalnya, saya mendorong kembali. Bagi saya, beberapa "tambalan" yang diusulkan untuk aliran Git klasik agak terlalu revolusioner. Saya pikir mereka mungkin melanggar ide utama, dan seluruh pendekatan akan gagal. Tetapi dengan pemikiran lebih lanjut, saya menyadari bahwa tweak ini tidak benar-benar merusak aliran Git. Sementara itu, mereka menjadikannya model percabangan Git yang lebih baik dengan menyelesaikan semua poin masalah yang disebutkan di atas.
Setelah sukses dengan pendekatan yang dimodifikasi dalam proyek itu, saya telah menggunakannya dalam proyek sumber tertutup lain dengan tim kecil di belakangnya, di mana saya adalah pemilik basis kode permanen dan satu atau dua pengembang outsourcing dari waktu ke waktu. Pada proyek ini, kami memasuki produksi enam bulan, dan sejak itu, kami telah menggunakan pengujian CI dan E2E selama lebih dari setahun, dengan rilis setiap bulan atau lebih.
Pengalaman saya secara keseluruhan dengan pendekatan percabangan baru ini sangat positif sehingga saya ingin membaginya dengan sesama pengembang untuk membantu mereka mengatasi kekurangan aliran Git klasik.
Persamaan dengan Aliran Git Klasik: Isolasi Pengembangan
Untuk isolasi kerja dalam aliran Git yang ditingkatkan, masih ada dua cabang berumur panjang, utama dan berkembang. (Pengguna masih memiliki perbaikan terbaru dan kemampuan rilis—dengan penekanan pada "kemampuan", karena ini bukan cabang lagi. Kami akan membahas detailnya di bagian perbedaan.)
Tidak ada skema penamaan resmi untuk cabang fitur aliran Git klasik. Anda baru saja keluar dari pengembangan dan bergabung kembali untuk mengembangkan saat fitur sudah siap. Tim dapat menggunakan konvensi penamaan apa pun yang mereka inginkan atau hanya berharap pengembang akan menggunakan nama yang lebih deskriptif daripada "cabang saya". Hal yang sama berlaku untuk aliran Git yang ditingkatkan.
Semua fitur yang terakumulasi di cabang pengembangan hingga beberapa titik batas akan membentuk rilis baru.
Gabungan Labu
Saya sangat menyarankan menggunakan squash merge untuk cabang fitur untuk menjaga sejarah tetap bagus dan linier sebagian besar waktu. Tanpa itu, grafik komit (dari alat GUI atau git log --graph
) mulai terlihat ceroboh ketika sebuah tim menyulap beberapa cabang fitur:
Tetapi bahkan jika Anda setuju dengan visual dalam skenario ini, ada alasan lain untuk berhenti. Tanpa meremas, komit tampilan riwayat—di antaranya git log
biasa (tanpa --graph
) dan juga GitHub—ceritakan kisah yang agak tidak koheren bahkan dengan skenario penggabungan yang paling sederhana:
Peringatan untuk menggunakan penggabungan squash adalah bahwa riwayat cabang fitur asli hilang. Tetapi peringatan ini bahkan tidak berlaku jika Anda menggunakan GitHub, misalnya, yang memperlihatkan riwayat asli lengkap dari cabang fitur melalui permintaan tarik yang digabungkan dengan squash, bahkan setelah cabang fitur itu sendiri dihapus.
Perbedaan dari Aliran Git Klasik: Rilis dan Perbaikan Terbaru
Mari kita melalui siklus rilis karena (semoga) ini adalah hal utama yang akan Anda lakukan. Ketika kami sampai pada titik di mana kami ingin merilis apa yang terakumulasi dalam pengembangan, itu benar-benar superset dari main. Setelah itu, perbedaan terbesar antara aliran Git klasik dan yang disempurnakan dimulai.

Rilis dalam Aliran Git yang Ditingkatkan
Setiap langkah membuat rilis dengan aliran Git yang ditingkatkan berbeda dari proses aliran Git klasik:
- Rilis didasarkan pada utama, bukan berkembang. Tandai ujung cabang utama saat ini dengan sesuatu yang berarti. Saya mengadopsi tag berdasarkan tanggal saat ini dalam format ISO 8601 yang diawali dengan "v"—misalnya, v2020-09-09 .
- Jika ada beberapa rilis dalam satu hari—misalnya, hotfix—formatnya dapat memiliki nomor urut atau huruf yang ditempelkan sesuai kebutuhan.
- Ketahuilah bahwa tag secara umum tidak sesuai dengan tanggal rilis. Mereka hanya memaksa Git untuk tetap mengacu pada bagaimana cabang utama terlihat saat proses rilis berikutnya dimulai.
- Dorong tag menggunakan
git push origin <the new tag name>
. - Setelah itu, sedikit kejutan: hapus cabang utama lokal Anda . Jangan khawatir, karena kami akan segera memulihkannya.
- Semua commit ke main masih aman—kami melindunginya dari pengumpulan sampah dengan menandai main pada langkah sebelumnya. Setiap komit ini—bahkan hotfix, seperti yang akan segera kita bahas—juga merupakan bagian dari pengembangan.
- Pastikan hanya satu orang dalam tim yang melakukan ini untuk rilis tertentu; itulah yang disebut peran "manajer rilis". Manajer rilis biasanya adalah anggota tim yang paling berpengalaman dan/atau paling senior, tetapi sebuah tim akan bijaksana untuk menghindari anggota tim tertentu mengambil peran ini secara permanen. Lebih masuk akal untuk menyebarkan pengetahuan di antara tim untuk meningkatkan faktor bus yang terkenal.
- Buat cabang utama lokal baru di ujung komit cabang pengembangan Anda .
- Dorong struktur baru ini menggunakan
git push --force
, karena repo jarak jauh tidak akan menerima "perubahan drastis" seperti itu dengan mudah. Sekali lagi, ini tidak seaman kelihatannya dalam konteks ini karena:- Kami hanya memindahkan penunjuk cabang utama dari satu komit ke komit lainnya.
- Hanya satu anggota tim tertentu yang melakukan perubahan ini pada satu waktu.
- Pekerjaan pengembangan sehari-hari terjadi di cabang pengembangan, jadi Anda tidak akan mengganggu pekerjaan siapa pun dengan memindahkan main dengan cara ini.
- Anda memiliki rilis baru Anda! Menyebarkannya ke lingkungan pementasan dan mengujinya. (Kita akan membahas pola CI/CD yang nyaman di bawah ini.) Setiap perbaikan langsung ke cabang utama, dan itu akan mulai menyimpang dari cabang pengembangan karena itu.
- Pada saat yang sama, Anda dapat mulai mengerjakan rilis baru di cabang pengembangan, keuntungan yang sama terlihat pada aliran Git klasik.
- Dalam kejadian yang tidak menguntungkan bahwa perbaikan terbaru diperlukan untuk apa yang saat ini dalam produksi (bukan rilis yang akan datang dalam tahap) pada saat ini, ada detail lebih lanjut tentang skenario ini di "Berurusan dengan perbaikan terbaru selama rilis aktif ..." di bawah ini.
- Ketika rilis baru Anda dianggap cukup stabil, terapkan versi final ke lingkungan produksi dan lakukan satu squash merge dari main untuk mengembangkan untuk mengambil semua perbaikan.
Perbaikan terbaru dalam Aliran Git yang Ditingkatkan
Kasus hotfix ada dua. Jika Anda melakukan perbaikan terbaru saat tidak ada rilis aktif —yaitu, tim sedang mempersiapkan rilis baru di cabang pengembangan—sangat mudah: Berkomitmen ke main, sebarkan perubahan Anda dan uji dalam staging hingga siap, lalu menyebarkan ke produksi.
Sebagai langkah terakhir, pilihlah komit Anda dari main untuk dikembangkan untuk memastikan rilis berikutnya akan berisi semua perbaikan. Jika Anda berakhir dengan beberapa komit perbaikan terbaru, Anda menghemat tenaga—terutama jika IDE Anda atau alat Git lainnya dapat memfasilitasinya—dengan membuat dan menerapkan tambalan alih-alih memetik ceri beberapa kali. Mencoba melakukan squash merge main to develop setelah rilis awal kemungkinan akan berakhir dengan konflik dengan kemajuan independen yang dibuat di cabang develop, jadi saya tidak menyarankan itu.
Menangani hotfix selama rilis aktif —yaitu, ketika Anda baru saja mendorong main dan masih mempersiapkan rilis baru—adalah bagian terlemah dari aliran Git yang ditingkatkan. Bergantung pada panjang siklus rilis dan tingkat keparahan masalah yang harus Anda selesaikan, selalu usahakan untuk menyertakan perbaikan dalam rilis baru itu sendiri—itulah cara termudah untuk dilakukan, dan tidak akan mengganggu keseluruhan alur kerja sama sekali.
Jika itu tidak boleh dilakukan—Anda harus memperkenalkan perbaikan dengan cepat, dan Anda tidak sabar menunggu rilis baru bersiap-siap—lalu bersiaplah untuk prosedur Git yang agak rumit:
- Buat cabang—kami akan menyebutnya “rilis baru”, tetapi tim Anda dapat mengadopsi konvensi penamaan apa pun di sini—pada komit yang sama dengan tip main. Dorong rilis baru.
- Hapus dan buat ulang cabang utama lokal di komit tag yang Anda buat sebelumnya untuk rilis aktif saat ini. Dorong paksa utama.
- Perkenalkan perbaikan yang diperlukan untuk main, deploy ke lingkungan staging, dan uji. Kapan pun itu siap, terapkan ke produksi.
- Menyebarkan perubahan dari main saat ini ke rilis baru baik melalui cherry-picking atau patch.
- Setelah itu, ulangi prosedur rilis: Beri tag pada ujung main saat ini dan dorong tag, hapus dan buat ulang main lokal di ujung cabang rilis baru, dan tekan paksa main.
- Anda mungkin tidak memerlukan tag sebelumnya, jadi Anda dapat menghapusnya.
- Cabang rilis baru sekarang berlebihan, jadi Anda juga dapat menghapusnya.
- Anda sekarang harus baik untuk pergi seperti biasa dengan rilis baru. Selesaikan dengan menyebarkan hotfix darurat dari main ke develop melalui cherry-picking atau patch.
Dengan perencanaan yang tepat, kualitas kode yang cukup tinggi, dan pengembangan yang sehat serta budaya QA, kecil kemungkinan tim Anda harus menggunakan metode ini. Adalah bijaksana untuk mengembangkan dan menguji rencana bencana seperti itu untuk meningkatkan aliran Git, untuk berjaga-jaga—tetapi saya tidak pernah perlu menggunakannya dalam praktik.
Pengaturan CI/CD di Atas Aliran Git yang Ditingkatkan
Tidak setiap proyek membutuhkan lingkungan pengembangan khusus. Mungkin cukup mudah untuk menyiapkan lingkungan pengembangan lokal yang canggih di setiap mesin pengembang.
Tetapi lingkungan pengembangan yang berdedikasi dapat berkontribusi terhadap budaya pembangunan yang lebih sehat. Menjalankan tes, mengukur cakupan tes, dan menghitung metrik kompleksitas pada cabang pengembangan sering kali mengurangi biaya kesalahan dengan menangkapnya dengan baik sebelum berakhir di staging.
Saya menemukan beberapa pola CI/CD sangat berguna ketika dikombinasikan dengan aliran Git yang ditingkatkan:
- Jika Anda memerlukan lingkungan pengembangan, siapkan CI untuk membangun, menguji, dan menerapkannya pada setiap komit ke cabang pengembangan. Cocokkan dalam pengujian E2E di sini juga, jika Anda memilikinya dan jika itu masuk akal dalam kasus Anda.
- Siapkan CI untuk membangun, menguji, dan menerapkan ke lingkungan staging pada setiap komit ke cabang utama. Pengujian E2E juga cukup bermanfaat pada saat ini.
- Mungkin tampak berlebihan untuk menggunakan pengujian E2E di kedua tempat, tetapi ingat bahwa perbaikan terbaru tidak akan terjadi dalam pengembangan. Memicu E2E pada komit ke main akan menguji hotfix dan perubahan sehari-hari sebelum mereka keluar, tetapi juga memicu komit untuk mengembangkan akan menangkap bug lebih awal.
- Konfigurasikan CI dengan cara yang memungkinkan tim Anda menerapkan build dari lingkungan utama ke produksi berdasarkan permintaan manual.
Pola seperti itu relatif sederhana, namun menyediakan mesin yang kuat untuk mendukung operasi pengembangan sehari-hari.
Model Aliran Git yang Ditingkatkan: Peningkatan dan Kemungkinan Batasan
Aliran Git yang ditingkatkan bukan untuk semua orang. Itu memanfaatkan taktik kekuatan kontroversial yang mendorong cabang utama, sehingga puritan mungkin membencinya. Dari sudut pandang praktis, tidak ada yang salah dengan itu.
Seperti disebutkan, perbaikan terbaru lebih menantang selama rilis tetapi masih memungkinkan. Dengan perhatian yang tepat pada QA, cakupan pengujian, dll. yang seharusnya tidak terjadi terlalu sering, jadi dari sudut pandang saya, ini adalah pertukaran yang valid untuk manfaat keseluruhan dari aliran Git yang ditingkatkan dibandingkan dengan aliran Git klasik. Saya akan sangat tertarik untuk mendengar bagaimana peningkatan tarif aliran Git dalam tim yang lebih besar dan dengan proyek yang lebih kompleks, di mana perbaikan terbaru mungkin lebih sering terjadi.
Pengalaman positif saya dengan model aliran Git yang disempurnakan juga sebagian besar berkisar pada proyek komersial sumber tertutup. Ini mungkin bermasalah untuk proyek sumber terbuka di mana permintaan tarik sering didasarkan pada turunan rilis lama dari pohon sumber. Tidak ada hambatan teknis untuk menyelesaikannya—hanya mungkin membutuhkan lebih banyak usaha daripada yang diharapkan. Saya menyambut umpan balik dari pembaca dengan banyak pengalaman di ruang sumber terbuka mengenai penerapan aliran Git yang ditingkatkan dalam kasus seperti itu.
Terima kasih khusus kepada rekan Toptal Antoine Pham atas peran kuncinya dalam mengembangkan ide di balik peningkatan aliran Git.
Bacaan Lebih Lanjut di Blog Teknik Toptal:
- Pengembangan Berbasis Batang vs. Aliran Git
- Alur Kerja Git untuk Pro: Panduan Git yang Baik
Sebagai Mitra Emas Microsoft, Toptal adalah jaringan elit pakar Microsoft Anda. Bangun tim berkinerja tinggi dengan para ahli yang Anda butuhkan - di mana pun dan kapan pun Anda membutuhkannya!