Bagaimana Anda mempertahankan kode pengembangan dan kode produksi? [Tutup]

137

Apa praktik terbaik dan aturan praktis yang harus diikuti sambil mempertahankan kode? Apakah praktik yang baik untuk hanya memiliki kode siap produksi di cabang pengembangan, atau haruskah kode terbaru yang belum teruji tersedia di cabang pengembangan?

Bagaimana kalian menjaga kode pengembangan dan kode produksi?

Edit - Pertanyaan tambahan - Apakah tim pengembangan Anda mengikuti protokol "commit-as-soon-as-mungkin-dan-sering-even-if-the-code-contains-minor-bugs-or-is-incomplete" atau "commit- Protokol ONLY-perfect-code "saat memasukkan kode ke cabang PENGEMBANGAN?

Mohit Ranka
sumber
Saya telah menjawab pertanyaan serupa (atau baik, pertanyaan dalam ruang / arah yang sama) sebelumnya, jadi Anda mungkin ingin memeriksa pertanyaan ini: Apa sajakah strategi yang baik untuk memungkinkan aplikasi yang diterapkan menjadi hotfixable?
Hingga
@revo: tunggu ... jawaban 2008 saya sudah kedaluwarsa? :) Saya rasa memang demikian. Sudah lebih dari 10 tahun: Saya telah mengedit jawaban saya.
VonC

Jawaban:

115

Perbarui 2019:

Saat ini, pertanyaannya akan dilihat dalam konteks menggunakan Git, dan 10 tahun penggunaan alur kerja pengembangan terdistribusi (terutama berkolaborasi melalui GitHub ) menunjukkan praktik terbaik umum:

  • masteradalah cabang yang siap untuk diterapkan ke produksi kapan saja: rilis berikutnya, dengan sekumpulan cabang fitur yang dipilih digabungkan master.
  • dev(atau cabang integrasi, atau ' next') adalah cabang tempat cabang fitur yang dipilih untuk rilis berikutnya diuji bersama
  • maintenance(atau hot-fix) branch adalah cabang untuk evolusi rilis saat ini / perbaikan bug, dengan kemungkinan penggabungan kembali ke devdan ataumaster

Alur kerja semacam itu (di mana Anda tidak menggabungkan devke master, tetapi di mana Anda hanya menggabungkan cabang fitur ke dev, kemudian jika dipilih, ke master, agar dapat dengan mudah melepaskan cabang fitur yang belum siap untuk rilis berikutnya) diimplementasikan di Git repo itu sendiri, dengan gitworkflow (satu kata, diilustrasikan di sini ).
Lihat lebih lanjut di rocketraman/gitworkflow. Sejarah melakukan ini vs Pengembangan Berbasis Batang dicatat dalam komentar dan diskusi artikel ini oleh Adam Dymitruk .

https://github.com/rocketraman/gitworkflow/raw/master/docs/images/topicgraduation.png

(sumber: Gitworkflow: A Task-Oriented Primer )

Catatan: dalam alur kerja terdistribusi tersebut, Anda dapat melakukan kapan pun Anda mau dan mendorong ke cabang pribadi beberapa WIP (Work In Progress) tanpa masalah: Anda akan dapat mengatur ulang (git rebase) komitmen Anda sebelum menjadikannya bagian dari cabang fitur.


Jawaban asli (Okt. 2008, 10+ tahun yang lalu)

Itu semua tergantung pada sifat urutan manajemen rilis Anda

Pertama, apakah semua yang ada di bagasi Anda benar-benar untuk rilis berikutnya ? Anda mungkin mengetahui bahwa beberapa fungsi yang saat ini dikembangkan adalah:

  • terlalu rumit dan masih perlu disempurnakan
  • tidak siap pada waktunya
  • menarik tetapi tidak untuk rilis berikutnya ini

Dalam kasus ini, trunk harus berisi upaya pengembangan saat ini, tetapi cabang rilis yang ditentukan lebih awal sebelum rilis berikutnya dapat berfungsi sebagai cabang konsolidasi di mana hanya kode yang sesuai (divalidasi untuk rilis berikutnya) yang digabungkan, kemudian diperbaiki selama fase homologasi, dan akhirnya dibekukan saat mulai diproduksi.

Dalam hal kode produksi, Anda juga perlu mengelola cabang tambalan Anda , sambil mengingat bahwa:

  • set tambalan pertama mungkin benar-benar dimulai sebelum rilis pertama ke produksi (artinya Anda tahu bahwa Anda akan masuk ke produksi dengan beberapa bug yang tidak dapat diperbaiki tepat waktu, tetapi Anda dapat memulai pekerjaan untuk bug tersebut di cabang terpisah)
  • cabang patch lainnya akan memiliki kemewahan untuk memulai dari label produksi yang terdefinisi dengan baik

Ketika datang ke cabang dev, Anda dapat memiliki satu trunk, kecuali jika Anda memiliki upaya pengembangan lain yang perlu Anda lakukan secara paralel seperti:

  • refactoring besar-besaran
  • pengujian pustaka teknis baru yang mungkin mengubah cara Anda memanggil sesuatu di kelas lain
  • awal dari siklus rilis baru di mana perubahan arsitektural penting perlu digabungkan.

Sekarang, jika siklus pengembangan-rilis Anda sangat berurutan, Anda dapat pergi seperti yang disarankan jawaban lain: satu trunk dan beberapa cabang rilis. Itu berfungsi untuk proyek-proyek kecil di mana semua pengembangan pasti akan masuk ke rilis berikutnya, dan hanya dapat dibekukan dan berfungsi sebagai titik awal untuk cabang rilis, tempat tambalan dapat dilakukan. Itu adalah proses nominalnya, tetapi segera setelah Anda memiliki proyek yang lebih kompleks ... itu tidak cukup lagi.


Untuk menjawab komentar Ville M.:

  • Perlu diingat bahwa cabang dev tidak berarti 'satu cabang per pengembang' (yang akan memicu 'kegilaan penggabungan', di mana setiap pengembang harus menggabungkan pekerjaan lain untuk melihat / mendapatkan pekerjaan mereka), tetapi satu cabang dev per pengembangan upaya.
  • Ketika upaya tersebut perlu digabungkan kembali ke dalam trunk (atau cabang "utama" atau rilis lainnya yang Anda tentukan), ini adalah pekerjaan pengembang, bukan - saya ulangi, BUKAN - Manajer SC (yang tidak akan tahu cara menyelesaikannya) penggabungan yang bertentangan). Pemimpin proyek dapat mengawasi penggabungan, yang berarti memastikan penggabungan dimulai / selesai tepat waktu.
  • siapa pun yang Anda pilih untuk benar-benar melakukan penggabungan, yang terpenting adalah:
    • agar memiliki pengujian unit dan / atau lingkungan perakitan tempat Anda dapat menerapkan / menguji hasil penggabungan.
    • untuk menentukan tag sebelum awal penggabungan agar dapat kembali ke keadaan sebelumnya jika penggabungan tersebut terbukti terlalu rumit atau agak lama untuk diselesaikan.
VonC
sumber
1
@Adam Terima kasih atas pengeditannya, dan maaf karena tidak mengatur atribusi yang tepat lebih awal.
VonC
Ha! Jangan khawatir. Anda telah melakukan banyak hal untuk komunitas di sini, Anda tidak dapat disalahkan untuk apa pun. Saya senang kami memiliki orang-orang seperti Anda yang melakukan begitu banyak pekerjaan untuk kepentingan semua orang di seluruh dunia!
Adam Dymitruk
Bagaimana Anda memastikan bahwa master(produksi) dan dev(integrasi) tidak berbeda? Apalagi dengan hot fixes? Apakah Anda secara teratur bergabung masterkembali dev, misalnya setelah melakukan rilis?
Bergi
@Bergi dengan gitworflow, dev adalah cabang sementara, dihapus dan dibuat ulang di atas setiap rilis baru. Tidak ada perbedaan di sana.
VonC
43

Kita gunakan:

  • cabang pengembangan secara eksklusif

hingga proyek hampir selesai, atau kami membuat versi pencapaian (mis. demo produk, versi presentasi), kemudian kami (secara teratur) mencabangkan cabang pengembangan kami saat ini menjadi:

  • rilis cabang

Tidak ada fitur baru yang masuk ke cabang rilis. Hanya bug penting yang diperbaiki di cabang rilis, dan kode untuk memperbaiki bug ini diintegrasikan kembali ke cabang pengembangan.

Proses dua bagian dengan pengembangan dan cabang yang stabil (rilis) membuat hidup jauh lebih mudah bagi kami, dan saya tidak percaya kami dapat meningkatkan bagian mana pun dengan memperkenalkan lebih banyak cabang. Setiap cabang juga memiliki proses pembangunannya sendiri, yang berarti setiap beberapa menit proses pembangunan baru muncul dan setelah kode checkin kita memiliki eksekusi baru dari semua versi dan cabang pembangunan dalam waktu sekitar setengah jam.

Terkadang kami juga memiliki cabang untuk satu pengembang yang mengerjakan teknologi baru dan belum terbukti, atau membuat bukti konsep. Tetapi umumnya itu hanya dilakukan jika perubahan memengaruhi banyak bagian basis kode. Ini terjadi rata-rata setiap 3-4 bulan dan cabang seperti itu biasanya diintegrasikan kembali (atau dibatalkan) dalam satu atau dua bulan.

Umumnya saya tidak suka ide setiap pengembang bekerja di cabangnya sendiri, karena Anda "lewati pergi dan langsung pindah ke neraka integrasi". Saya sangat menyarankan untuk tidak melakukannya. Jika Anda memiliki basis kode yang sama, Anda semua harus mengerjakannya bersama-sama. Hal ini membuat pengembang lebih waspada tentang check in mereka, dan dengan pengalaman setiap pembuat kode tahu perubahan mana yang berpotensi merusak build sehingga pengujian lebih ketat dalam kasus seperti itu.

Pada pertanyaan awal check-in:

Jika Anda hanya memerlukan PERFECT CODE untuk diperiksa, maka sebenarnya tidak ada yang harus diperiksa. Tidak ada kode yang sempurna, dan agar QA dapat memverifikasi dan mengujinya, kode harus berada di cabang pengembangan sehingga dapat dijalankan yang baru.

Bagi kami, itu berarti setelah fitur selesai dan diuji oleh pengembang, fitur itu akan diperiksa. Ini bahkan dapat diperiksa jika ada bug yang diketahui (tidak fatal), tetapi dalam kasus itu orang-orang yang akan terpengaruh oleh bug adalah biasanya diinformasikan. Kode yang tidak lengkap dan sedang dalam proses juga dapat diperiksa tetapi hanya jika tidak menyebabkan efek negatif yang jelas, seperti crash atau merusak fungsionalitas yang ada.

Kadang-kadang kombinasi kode & data checkin yang tidak dapat dihindari akan membuat program tidak dapat digunakan sampai kode baru dibuat. Paling tidak yang kita lakukan adalah menambahkan "WAIT FOR BUILD" di komentar check-in dan / atau mengirim email.

steffenj
sumber
1
Saya memilihnya. Ini mirip dengan apa yang kami lakukan, tetapi kami membuat semua perubahan dalam pengembangan dan kemudian mencoba menggabungkan perbaikan bug tersebut ke cabang rilis .. Tidak berfungsi. Namun, saya pikir jika kita mengubah untuk melakukan semua perbaikan bug dalam rilis dan bergabung ke dalam pengembangan, itu akan memperbaikinya.
TheCodeMonk
2
Anda menyiratkan bahwa QA menguji cabang pengembangan, bukankah lebih baik jika mereka memeriksa cabang rilis? Dengan cara itu saya dapat mulai mengerjakan fitur baru saya yang tidak akan disertakan dalam rilis berikutnya (dan mungkin merusak sesuatu) sementara pada saat itu QA akan menguji kode yang ada tanpa mengganggu fitur baru saya?
BornToCode
15

Untuk apa nilainya, begitulah cara kami melakukannya.

Sebagian besar pengembangan dilakukan di trunk, meskipun fitur eksperimental atau hal-hal yang dapat merusak sistem secara signifikan cenderung mendapatkan cabangnya sendiri. Ini bekerja dengan cukup baik karena itu berarti setiap pengembang selalu memiliki versi terbaru dari semuanya dalam copy pekerjaan mereka.

Ini berarti bahwa penting untuk menjaga bagasi tetap berfungsi dengan baik, karena sangat mungkin untuk merusaknya sepenuhnya. Dalam praktiknya, hal itu tidak sering terjadi, dan jarang menjadi masalah yang signifikan.

Untuk rilis produksi, kami mencabangkan trunk, berhenti menambahkan fitur baru, dan mengerjakan perbaikan bug serta menguji cabang (secara teratur menggabungkan kembali ke trunk) hingga siap untuk dirilis. Pada titik mana kita melakukan penggabungan terakhir ke dalam trunk untuk memastikan semuanya ada di sana, lalu lepaskan.

Pemeliharaan kemudian dapat dilakukan pada cabang rilis seperlunya, dan perbaikan tersebut dapat dengan mudah digabungkan kembali ke dalam trunk.

Saya tidak mengklaim ini sebagai sistem yang sempurna (dan masih memiliki beberapa lubang - menurut saya manajemen rilis kami belum cukup ketat prosesnya), tetapi berfungsi dengan cukup baik.

Dan
sumber
bekerja cukup baik dan cukup sederhana juga untuk pengembang kode-saja-non-vcs-druids.
Matthieu
12

Mengapa tidak ada yang masih menyebutkan ini? Model percabangan Git yang sukses .

Bagi saya model percabangan terbaik!

Jika proyek Anda kecil, jangan gunakan sepanjang waktu semua cabang yang berbeda (mungkin Anda bisa melewati cabang fitur untuk fitur kecil). Tapi sebaliknya, itulah cara melakukannya!

model percabangan

Philippe
sumber
4
Ya, kecuali jika seringkali agak terlalu rumit / lengkap, seperti yang diilustrasikan oleh scottchacon.com/2011/08/31/github-flow.html .
VonC
Saya setuju. Pahami model percabangan aliran git (yang memecahkan banyak masalah) dan sederhanakan agar sesuai dengan kebutuhan Anda. Dan aliran GitHub memerlukan penerapan cepat tetapi itu tidak selalu memungkinkan ... Ini kurang lebih adalah model percabangan yang kami gunakan dalam proyek saya (untuk menyederhanakannya) tetapi kami menghadapi kasus di mana kami ingin sekali menggunakan model aliran git: (dan itu membuat kami berada dalam masalah besar :(
Philippe
1
Cara saya melihatnya, ini pada dasarnya menyalin semua yang dikatakan VonC kira-kira 1 tahun sebelumnya (pada jawabannya), tetapi dengan cara yang lebih rinci dan dengan gambar yang bagus!
cregox
6

Kode pengembangan di cabang, Kode langsung diberi tag di Batang.

Tidak perlu ada aturan "hanya melakukan kode yang sempurna" - apa pun yang terlewat oleh pengembang harus diambil di empat tempat: tinjauan kode, pengujian cabang, pengujian regresi, pengujian QA akhir.

Berikut penjelasan langkah demi langkah yang lebih rinci:

  1. Lakukan semua pengembangan di cabang, lakukan secara teratur saat Anda pergi.
  2. Review Kode Independen perubahan setelah semua pengembangan selesai.
  3. Kemudian berikan cabang ke Pengujian.
  4. Setelah pengujian cabang selesai, gabungkan kode ke cabang Release Candidate.
  5. Cabang Kandidat Rilis diuji regresi setelah setiap penggabungan individu.
  6. Pengujian QA dan UA akhir dilakukan pada RC setelah semua cabang dev digabungkan.
  7. Setelah QA dan UAT dilewati, gabungkan cabang rilis ke cabang MAIN / TRUNK.
  8. Terakhir, beri tag Batang pada saat itu, dan terapkan tag tersebut ke Live.
Peter Boughton
sumber
4

dev masuk trunk (gaya svn) dan rilis (kode produksi) mendapatkan cabangnya sendiri

Ini adalah "Model cabang demi tujuan" (gambar 3 dalam Pentingnya model percabangan /! \ Pdf)

PW.
sumber
3

Kami menyelesaikan masalah ini dengan memisahkan kode produksi (batang utama) dari kode pengembangan (di mana setiap pengembang memiliki cabangnya sendiri).

Tidak ada kode yang diizinkan ke dalam kode produksi sebelum diperiksa secara menyeluruh (oleh QA dan peninjau kode).

Dengan cara ini tidak ada kebingungan tentang kode mana yang berfungsi, itu selalu merupakan cabang utama.

Grimtron
sumber
2

Oh ya - satu hal lagi - kami menyimpan kode non-produksi (yaitu kode yang TIDAK AKAN PERNAH dirilis - misalnya skrip alat, utilitas pengujian) di cvs HEAD. Biasanya itu perlu ditandai dengan jelas sehingga tidak ada yang "secara tidak sengaja" melepaskannya.

MarkR
sumber
2
mungkin ini akan lebih baik sebagai edit dari jawaban sebelumnya.
Richard Harrison
6
Dia mengatakan CVS. :-)
Hingga
2

Kami kembangkan di batang yang kemudian bercabang setiap dua minggu dan mulai berproduksi. Hanya bug kritis yang diperbaiki di cabang, sisanya bisa menunggu dua minggu lagi.

Untuk trunk, satu-satunya aturan adalah bahwa komit tidak boleh merusak apa pun. Untuk mengelola wip-code dan kode yang belum teruji, kami hanya menambahkan statments yang sesuai agar mudah untuk mengaktifkan dan menonaktifkan.

Pada dasarnya adalah mungkin untuk batang cabang setiap saat dan memasukkannya ke dalam produksi.

John Nilsson
sumber
0

Saya menggunakan git dan saya memiliki 2 cabang: master dan maint

  • master - kode pengembangan
  • pemeliharaan - kode produksi

ketika saya melepaskan kode ke produksi, saya menandainya dan saya menggabungkan master untuk memelihara cabang. Saya selalu menerapkan dari cabang pemeliharaan . Patch dari cabang pengembangan saya memilihnya untuk memelihara cabang dan menerapkan patch.

Vitalie
sumber
0

Kami memiliki cabang "rilis" yang berisi apa yang saat ini diproduksi atau akan segera diterapkan (sudah melewati sebagian besar QA)

Setiap proyek, atau dalam beberapa kasus unit lain, memiliki cabangnya sendiri yang bercabang dari rilis.

Perubahan dilakukan, oleh pengembang di proyek, ke dalam cabang proyek mereka sendiri. Secara berkala, rilis digabungkan kembali menjadi cabang pengembangan.

Setelah paket kerja di cabang semuanya QA (pengujian unit, pengujian sistem, tinjauan kode, tinjauan QA dll), cabang digabungkan ke dalam cabang rilis. Build baru dibangun dari cabang rilis, dan validasi akhir terjadi pada versi itu.

Prosesnya pada dasarnya OK sampai masalah ditemukan setelah penggabungan dilakukan. Jika WP "macet" setelah digabungkan, itu menahan semuanya setelah itu sampai diperbaiki (kita tidak dapat melakukan rilis lain sampai yang macet dilepaskan).


Ini juga agak fleksibel - perubahan yang sangat sepele dapat terjadi secara langsung pada cabang rilis jika dirilis dalam skala waktu yang sangat singkat (seperti 1-2 hari atau lebih).

Jika perubahan dilakukan langsung ke produksi karena alasan tertentu (masalah kritis produksi yang memengaruhi pelanggan yang memerlukan perubahan kode segera untuk diperbaiki), perubahan tersebut akan dimasukkan kembali ke BRANCH_RELEASE. Itu hampir tidak pernah terjadi.

MarkR
sumber
0

Itu tergantung proyeknya. Kode web kita diperiksa dengan cukup konsisten, sementara kode aplikasi kita hanya diperiksa jika dikompilasi. Saya perhatikan bahwa ini sangat mirip dengan cara kami merilis sesuatu. Barang web naik kapan pun bisa sementara aplikasi mencapai tenggat waktu yang sulit. Saya belum pernah melihat penurunan kualitas dalam kedua metode tersebut.

icco
sumber