Apa model percabangan Git yang cocok untuk Anda?

379

Perusahaan kami saat ini menggunakan model percabangan trunk / rilis / hotfix sederhana dan ingin saran tentang model percabangan apa yang paling cocok untuk perusahaan Anda atau proses pengembangan.

  1. Alur kerja / model percabangan

    Di bawah ini adalah tiga deskripsi utama dari hal ini yang telah saya lihat, tetapi mereka sebagian bertentangan satu sama lain atau tidak cukup jauh untuk memilah masalah-masalah berikutnya yang telah kita hadapi (seperti dijelaskan di bawah). Jadi tim kami sejauh ini default untuk solusi yang tidak terlalu bagus. Apakah Anda melakukan sesuatu yang lebih baik?

  2. Penggabungan vs rebasing (kusut vs riwayat berurutan)

    Haruskah seseorang pull --rebaseatau menunggu dengan bergabung kembali ke garis utama sampai tugas Anda selesai? Secara pribadi saya condong ke arah penggabungan karena ini mempertahankan ilustrasi visual yang menjadi dasar tugas dimulai dan diselesaikan, dan saya bahkan lebih suka merge --no-ffuntuk tujuan ini. Namun memiliki kelemahan lain. Juga banyak yang belum menyadari properti berguna dari penggabungan - bahwa itu tidak komutatif (menggabungkan cabang topik menjadi master tidak berarti menggabungkan master ke cabang topik).

  3. Saya mencari alur kerja alami

    Terkadang kesalahan terjadi karena prosedur kami tidak menangkap situasi tertentu dengan aturan sederhana. Sebagai contoh, perbaikan yang diperlukan untuk rilis sebelumnya tentu saja harus didasarkan pada downstream yang cukup untuk memungkinkan penggabungan upstream ke semua cabang yang diperlukan (apakah penggunaan istilah-istilah ini cukup jelas?). Namun kebetulan bahwa perbaikan membuatnya menjadi master sebelum pengembang menyadari itu harus ditempatkan lebih jauh ke hilir, dan jika itu sudah didorong (bahkan lebih buruk, digabung atau sesuatu berdasarkan itu) maka opsi yang tersisa adalah memetik ceri, dengan bahaya yang terkait. Aturan sederhana seperti apa yang Anda gunakan?Juga dalam hal ini termasuk kejanggalan dari satu cabang topik tidak termasuk cabang topik lainnya (dengan asumsi mereka bercabang dari baseline umum). Pengembang tidak ingin menyelesaikan fitur untuk memulai dengan perasaan lain seperti kode yang baru saja mereka tulis sudah tidak ada lagi

  4. Bagaimana cara menghindari membuat konflik gabungan (karena cherry-pick)?

    Apa yang tampak seperti cara pasti untuk menciptakan konflik penggabungan adalah dengan memetik antar cabang, mereka tidak akan pernah bisa digabungkan lagi? Apakah menerapkan komit yang sama dalam pengembalian (bagaimana melakukan ini?) Di cabang mana pun mungkin menyelesaikan situasi ini? Ini adalah salah satu alasan saya tidak berani mendorong alur kerja berbasis penggabungan.

  5. Bagaimana cara membusuk menjadi cabang topikal?

    Kami menyadari bahwa akan luar biasa untuk mengumpulkan integrasi selesai dari cabang topik, tetapi sering kali kerja oleh pengembang kami tidak didefinisikan dengan jelas (kadang-kadang sesederhana "mencari-cari") dan jika beberapa kode sudah masuk ke topik "misc", tidak bisa dibawa keluar dari sana lagi, sesuai pertanyaan di atas? Bagaimana Anda bekerja dengan mendefinisikan / menyetujui / lulus / melepaskan cabang topik Anda?

  6. Prosedur yang tepat seperti tinjauan kode dan kelulusan tentu saja akan menyenangkan.

    Tetapi kita tidak bisa menjaga hal-hal yang tidak terurai cukup untuk mengelola ini - ada saran? cabang integrasi, ilustrasi?

Di bawah ini adalah daftar pertanyaan terkait:

Periksa juga apa yang ditulis oleh SCM Plastik tentang pengembangan berbasis tugas , dan jika Plastik bukan pilihan Anda, pelajari model percabangan nvie dan skrip pendukungnya .

HaiQ CJ
sumber
2
Hah, terima kasih, memang sudah ... sebenarnya saya sudah membaca sebagian besar ... hal :-). Ini adalah sesuatu yang saya dikenal - tidak puas dengan solusi biasa-biasa saja tetapi terus mencari yang sempurna. Seringkali ini adalah kesalahan, tetapi dalam hal ini banyak yang dipertaruhkan dan solusi yang ada terlalu berantakan atau miskin sehingga saya harus terus mencari. Jadi saya memutuskan untuk membuat daftar semua masalah yang saya miliki dengannya.
HiQ CJ
Blog Plastic SCM melemparkan opini mereka ke dalam diskusi, setidaknya wawasan: codicesoftware.blogspot.com/2010/08/…
HiQ CJ
1
Anda harus berhati-hati saat menggunakan "menggabungkan --tidak-ff", periksa ini untuk beberapa peringatan sandofsky.com/blog/git-workflow.html
Doppelganger
1
@Doppelganger Saya akan tertarik pada seberapa spesifik --no-ff yang seharusnya berkontribusi pada masalah yang dijelaskan dalam tautan yang Anda posting. Bagi saya masalah yang dijelaskan ada kegagalan membagi dua dengan pos pemeriksaan dilakukan, dan kegagalan git menyalahkan untuk membantu dalam kasus itu - tapi saya gagal melihat bagaimana "--tidak-ff" mengubah apa pun, sebagai lawan dari tidak menggunakannya. Penulis mengeluh bahwa penggabungan dengan --no-ff tidak membuat file diubah - namun tanpa itu, file tidak akan dimodifikasi juga, Anda hanya akan melihat komit yang lebih lama dalam riwayat Anda, bukan?
codeling
Model percabangan lainnya: cactus model barro.github.io/2016/02/… , model utama bitsnbites.eu/a-stable-mainline-branching-model-for-git . Kedua model percabangan ini menawarkan pendekatan lain selain gitflow.
Mathieu Momal

Jawaban:

91

Fitur yang paling perlu disadari oleh pengembang baru untuk DVCS adalah tentang proses publikasi :

  • Anda dapat mengimpor (mengambil / menarik) repo jarak jauh apa pun yang Anda butuhkan
  • Anda dapat mempublikasikan (mendorong) ke repo (kosong) yang Anda inginkan

Dari itu, Anda dapat menghormati beberapa aturan untuk membuat pertanyaan Anda lebih mudah:

Sekarang:

Alur kerja / model percabangan :

setiap alur kerja ada untuk mendukung proses manajemen rilis , dan itu disesuaikan untuk setiap proyek.
Apa yang dapat saya tambahkan ke alur kerja yang Anda sebutkan adalah: setiap pengembang tidak boleh membuat cabang fitur, hanya cabang "pengembang saat ini", karena kenyataannya adalah: pengembang sering tidak tahu apa yang akan dihasilkan cabangnya: satu fitur, beberapa (karena itu akhirnya menjadi fitur yang terlalu kompleks), tidak ada (karena tidak siap dalam waktu untuk rilis), fitur lain (karena yang asli telah "berubah"), ...

Hanya "integrator" yang harus membuat cabang fitur resmi pada repo "sentral", yang kemudian dapat diambil oleh pengembang untuk mengubah / menggabungkan bagian dari pekerjaan mereka yang sesuai dengan fitur itu.

Penggabungan vs rebasing (kusut vs riwayat berurutan) :

Saya suka jawaban saya yang Anda sebutkan (" Deskripsi alur kerja untuk penggunaan git untuk pengembangan in-house ")

Saya mencari alur kerja alami :

untuk perbaikan, ini dapat membantu mengasosiasikan setiap perbaikan dengan tiket dari pelacakan bug, yang membantu pengembang mengingat di mana (yaitu cabang mana, yaitu cabang khusus "untuk perbaikan") ia harus melakukan modifikasi tersebut.
Kemudian kait dapat membantu melindungi repo pusat terhadap dorongan dari perbaikan bug yang tidak divalidasi atau dari cabang yang tidak boleh didorong. (tidak ada solusi spesifik di sini, semua ini perlu disesuaikan dengan lingkungan Anda)

Bagaimana cara menghindari membuat konflik gabungan (karena cherry-pick)?

Seperti yang dinyatakan oleh Jakub Narębski dalam jawabannya , memetik ceri harus disediakan untuk situasi yang jarang terjadi di mana diperlukan.
Jika pengaturan Anda melibatkan banyak memetik ceri (yaitu "tidak jarang"), maka ada sesuatu yang mati.

Apakah menerapkan komit yang sama dalam pengembalian (bagaimana melakukan ini?)

git revert harus mengurus itu, tetapi itu tidak ideal.

Bagaimana cara membusuk menjadi cabang topikal?

Selama cabang belum didorong ke mana-mana, pengembang harus menata ulang sejarah komitmennya (setelah ia akhirnya melihat pengembangannya mengambil bentuk yang lebih pasti dan stabil) menjadi:

  • beberapa cabang jika diperlukan (satu dengan fitur yang jelas diidentifikasi)
  • seperangkat komitmen yang koheren dalam satu cabang (lihat Memangkas Git Checkins )

Prosedur yang tepat seperti tinjauan kode dan kelulusan?

Cabang-cabang integrasi (dalam integrasi khusus) dapat membantu pengembang untuk:

  • rebase perkembangannya di atas cabang integrasi jarak jauh itu (pull --rebase)
  • selesaikan secara lokal
  • dorong pengembangan ke repo itu
  • periksa dengan integrator yang tidak menghasilkan kekacauan;)
VONC
sumber
@UncleCJ: seperti yang Anda lihat, ini bukan jawaban akhir untuk "pertanyaan akhir" Anda;)
VonC
Saya mengerti, dan saya memiliki perasaan ironi yang baik juga, tidak apa-apa ;-)
HiQ CJ
3
@UncleCJ hulu adalah tempat Anda secara teratur menarik dari, dari posting saya, di mana semua komit berakhir (versi rilis atau trunk dalam bahasa SVN). Downstream adalah semua orang di bawah mereka. Mengirim barang ke hulu adalah proses memasukkannya ke dalam rilis repo (seperti linux-2.6) dan hilir adalah perubahan dari sana keluar, atau dari repositori Anda seperti dikatakan manajer mengembangkan fitur seperti itu untuk pelayan Anda ... Saya tim berarti.
2
@UncleCJ: "Saya masih merasa sulit untuk memotong checkin Anda untuk mencapai sejarah sekuensial yang ketat": lebih mudah dengan Git1.7 dan rebase --interactive --autosquashyang akan bergerak secara otomatis semua komit dengan awal yang sama dengan pesan komit yang sama. Jika komit tersebut menggunakan nomor tiket (misalnya), bahkan jika perbaikan yang terkait dengan tiket itu tidak dilakukan secara berurutan pada saat itu, autosquash memungkinkan untuk menata ulang secara cepat komit tersebut.
VonC
1
@UncleCJ: "histori sekuensial yang ketat (apakah ini perlu atau tidak ?!)": tidak selalu diperlukan, tetapi membantu menjaga jejak dependensi fungsional ( stackoverflow.com/questions/881092/… ) dan konflik semantik ( stackoverflow.com/questions / 2514502 / ... )
VonC
21

Saya pikir, dan saya mungkin salah, bahwa salah satu hal yang paling disalahpahami tentang git adalah sifatnya yang terdistribusi. Ini membuatnya sangat berbeda untuk mengatakan subversi dalam cara Anda dapat bekerja meskipun Anda dapat meniru perilaku SVN yang Anda inginkan. Masalahnya cukup banyak alur kerja yang akan dilakukan, yang bagus tetapi juga menyesatkan.

Jika saya memiliki pemahaman saya tentang pengembangan kernel (saya akan fokus pada hal itu) dengan benar, setiap orang memiliki repositori git mereka sendiri untuk mengembangkan kernel. Ada satu repositori, linux-2.6.git, dijaga oleh Torvalds, yang bertindak sebagai repositori rilis. Orang-orang mengkloning dari sini jika mereka ingin mulai mengembangkan fitur yang menentang cabang "release".

Repositori lain melakukan pengembangan. Idenya adalah untuk mengkloning dari linux-2.6, bercabang sebanyak yang Anda suka sampai Anda memiliki fitur "baru" yang berfungsi. Kemudian, ketika ini sudah siap, Anda dapat membuatnya tersedia untuk seseorang yang dianggap tepercaya, yang akan menarik cabang ini dari repositori Anda ke milik mereka dan menggabungkannya ke arus utama. Dalam kernel linux ini terjadi pada beberapa tingkatan (letnan tepercaya) sampai mencapai linux-2.6.git pada titik mana ia menjadi "kernel".

Sekarang di sinilah itu membingungkan. Nama cabang tidak perlu konsisten di seluruh repositori sama sekali. Jadi saya bisa git pull origin master:vanilla-codedan mendapatkan cabang dari originmaster di cabang di repositori saya bernama vanilla-code. Memberikan saya tahu apa yang terjadi, itu benar-benar tidak masalah - itu didistribusikan dalam arti bahwa semua repositori adalah rekan satu sama lain dan tidak hanya dibagi di beberapa komputer seperti SVN.

Jadi, dengan semua ini dalam pikiran:

  1. Saya pikir terserah masing-masing programmer bagaimana mereka melakukan percabangan. Yang Anda butuhkan hanyalah repositori pusat untuk mengelola rilis, dll. Trunk bisa saja head. Rilis bisa berupa tag atau cabang dan perbaikan terbaru mungkin merupakan cabang dalam dirinya sendiri. Bahkan, saya mungkin akan melakukan rilis sebagai cabang sehingga Anda dapat terus menambalnya.
  2. Saya akan bergabung dan tidak akan rebase. Jika misalnya Anda mengambil repositori, clone itu, cabang dan melakukan beberapa dev, kemudian tarik dari Anda originAnda harus, dalam repositori Anda, mungkin membuat cabang lain dan menggabungkan terbaru masterdalam yourbranchsehingga orang lain dapat menarik perubahan dengan usaha sesedikit bisa jadi. Sangat jarang ada kebutuhan untuk benar-benar rebase, dalam pengalaman saya.
  3. Saya pikir ini adalah kasus memahami cara kerja Git dan apa yang bisa dilakukannya. Butuh beberapa saat dan banyak komunikasi yang baik - Saya hanya benar-benar mulai memahami apa yang terjadi ketika saya mulai menggunakan git dengan pengembang lain dan bahkan sekarang, beberapa hal yang saya tidak yakin.
  4. Menggabungkan konflik bermanfaat. Saya tahu, saya tahu, Anda ingin semuanya berfungsi, tetapi kenyataannya adalah perubahan kode dan Anda harus menggabungkan hasilnya menjadi sesuatu yang berfungsi. Menggabungkan konflik sebenarnya hanyalah pemrograman yang lebih banyak. Saya tidak pernah menemukan penjelasan yang mudah untuk apa yang harus dilakukan tentang mereka, jadi di sini adalah: perhatikan file-file yang menggabungkan konflik, buka dan ubah menjadi apa yang seharusnya, git add .dan kemudian git commit.
  5. Namun itu cocok. Seperti yang telah saya katakan, setiap pengguna git repositori adalah milik mereka sendiri untuk bermain dan nama - nama cabang tidak harus sama . Jika Anda memiliki repositori pementasan, misalnya, Anda bisa menerapkan skema penamaan, tetapi Anda tidak perlu melakukannya untuk setiap pengembang, hanya di repo rilis.
  6. Ini adalah tahap penggabungan. Anda hanya bergabung ke cabang rilis dll ketika Anda mempertimbangkan kode untuk ditinjau / lulus pengujian kualitas.

Saya harap itu membantu. Saya menyadari VonC sebagai baru saja memposting penjelasan yang sangat mirip ... Saya tidak bisa mengetik cukup cepat!

Edit beberapa pemikiran lebih lanjut tentang cara menggunakan git dalam pengaturan komersial, karena ini tampaknya relevan dengan OP dari komentar:

  • Repositori rilis, kami akan menyebutnya product.git, dapat diakses oleh sejumlah programmer senior / orang teknis yang bertanggung jawab untuk benar-benar menjaga produk itu sendiri. Mereka analog dengan peran pengelola dalam OSS.
  • Programmer ini mungkin juga sebagian memimpin pengembangan versi baru, sehingga mereka mungkin juga mengkodekan diri mereka sendiri dan memelihara repositori varios. Mereka mungkin mengelola repositori pementasan untuk fitur yang benar-benar baru dan mereka mungkin juga memiliki repositori mereka sendiri.
  • Di bawah mereka adalah programmer yang bertanggung jawab untuk mengembangkan bit individual. Misalnya, seseorang mungkin bertanggung jawab atas pekerjaan UI. Karena itu mereka mengelola repositori UI.git.
  • Di bawah mereka adalah programmer sebenarnya yang mengembangkan fitur sebagai pekerjaan sehari-hari mereka.

Jadi apa yang terjadi? Yah, setiap orang menarik di awal setiap hari dari sumber "upstream" yaitu repositori rilis (yang juga mungkin akan berisi materi terbaru dari pengembangan hari-hari sebelumnya). Semua orang melakukan ini, secara langsung. Ini akan pergi pada cabang di repositori mereka, mungkin disebut "master" atau mungkin jika Anda saya disebut "terbaru". Programmer kemudian akan melakukan beberapa pekerjaan. Pekerjaan ini mungkin sesuatu yang mereka tidak yakin, jadi mereka membuat cabang, melakukan pekerjaan. Jika tidak berhasil, mereka dapat menghapus cabang dan kembali. Jika ya, mereka harus bergabung ke cabang utama yang sedang mereka kerjakan. Kami akan mengatakan ini adalah programmer UI yang sedang dikerjakan latest-uisehingga ia tidak git checkout latest-uidiikuti olehgit merge abc-ui-mywhizzynewfeature. Dia kemudian memberi tahu pimpinan teknisnya (pemimpin UI) hei, saya telah menyelesaikan tugas seperti itu, tarik dari saya. Jadi pemimpin UI tidak git pull user-repo lastest-ui:lastest-ui-suchafeature-abc. Pimpinan UI kemudian melihatnya di cabang itu dan berkata, sebenarnya, itu sangat bagus, saya akan menggabungkannya ui-latest. Dia mungkin kemudian memberitahu semua orang di bawahnya untuk menarik darinya di ui-latestcabang mereka atau nama apa pun yang telah mereka berikan kepada mereka, sehingga fitur tersebut dieksplorasi oleh para devs. Jika tim senang, pemimpin UI mungkin meminta pemimpin pengujian untuk menarik darinya dan menggabungkan perubahan. Ini menyebar ke semua orang (hilir perubahan) yang mengujinya dan mengirimkan laporan bug dll. Akhirnya, jika fitur tersebut melewati pengujian dll, salah satu pemimpin teknis utama mungkin menggabungkannya ke dalam salinan program saat ini, pada titik mana semua perubahan kemudian disebarkan kembali. Dan seterusnya.

Ini bukan cara kerja "tradisional" dan dirancang untuk menjadi "didorong oleh teman" daripada "hierarkis" seperti SVN / CVS. Intinya, setiap orang memiliki akses komit, tetapi hanya secara lokal. Ini adalah akses ke repositori dan repositori mana yang Anda tunjuk sebagai repo rilis yang memungkinkan Anda untuk menggunakan hierarki.


sumber
Terima kasih banyak atas jawaban Anda yang luas (dan suara), saya akan membacanya beberapa kali lebih banyak untuk memeras informasi yang berguna darinya. Namun, kami adalah perusahaan, bukan komite pengembangan OSS ;-), dan saya harus membantu pengembang saya dengan pedoman yang lebih jelas daripada "bermain-main seperti yang Anda inginkan di repositori Anda sendiri". Mari kita lihat ke mana pos ini mengarah, saya merasakan momentum yang baik, tetap datang!
HiQ CJ
@VonC Terima kasih. @UncleCJ benar, tetapi Anda, saya yakin, memiliki manajer rilis dll. Siapa pun yang memiliki akses ke repositori dapat melakukan hal-hal ini. Adapun pengembangan, mengapa tidak memberikan pengembang kebebasan, dengan alasan, untuk bercabang? Asalkan Anda memiliki beberapa protokol untuk menyetujui penggabungan dan repositori pusat Anda dinamai sesuka Anda, tidak ada masalah. Karena itu, skema penamaan yang umum bukanlah ide yang buruk. Saya cenderung menggunakan inisialisasi-versi-fitur-cabang untuk cabang pribadi dan versi untuk cabang.
@UncleCJ Saya telah menambahkan contoh untuk bagaimana ini bisa bekerja di perusahaan. Ini pada dasarnya peran OSS diganti dengan manajer, tetapi Anda mendapatkan idenya. Ini memiliki manfaat tambahan dibandingkan SVN bahwa devs Anda dapat bekerja offline juga (mereka hanya membutuhkan jaring untuk menarik / mendorong) dan saya pikir membuatnya lebih mudah untuk menguji fitur, jika Anda menerapkannya dengan baik.
Wow, itu sebenarnya contoh yang bagus, kita mungkin mulai menggunakan sesuatu seperti itu untuk wisuda. Saya tidak begitu berarti bahwa karena kita tidak melakukan OSS semua orang harus diatur, kami sebenarnya adalah tim yang cukup kecil dan datar, tetapi kami harus mencoba untuk berkolaborasi secara efisien pada jadwal yang ketat dan juga belajar sebagai sebuah tim . Itu sebabnya saya di sini mengajukan pertanyaan-pertanyaan bodoh ini sehingga saya dapat membantu anggota tim lainnya nanti :-). Saya juga menyadari dari # git bahwa garis dasar yang tidak jelas dikombinasikan dengan tekanan untuk mempersingkat waktu memimpin membuat kita tersandung ... akan kembali lagi nanti.
HiQ CJ
Itu cukup adil - saya baru-baru ini ada di sana dan itulah tepatnya bagaimana saya mengambil contoh itu, dengan mencobanya dan banyak gagal ... dan juga beradaptasi dengan cara kerja beberapa proyek OSS. Saya kira masalah besar sebenarnya adalah tidak masalah bagaimana Anda bercabang dan di mana repositori Anda berada ... Anda dapat mendefinisikan ini dengan cara apa pun yang Anda inginkan yang merupakan kejutan nyata bagi saya! Tetapi memungkinkan Anda untuk melakukan beberapa hal menarik. Pokoknya, semoga sukses dan bersenang-senang!
9

Model yang saya gunakan dengan hasil yang baik adalah sebagai berikut:

Setiap orang repo "diberkati" mendorong dan menarik ke / dari, pada dasarnya topologi client-server.

Tidak ada cabang utama sehingga tidak ada pengembang yang bisa mendorong kode apa pun ke "arus utama".

Semua perkembangan terjadi pada cabang topik. Kami namespace nama untuk dengan mudah mendeteksi siapa yang bertanggung jawab untuk itu: jn / newFeature atau jn / issue-1234

Ada juga pemetaan 1-ke-1 yang dekat antara cabang dan kartu kanban / scrum di papan tulis.

Untuk melepaskan cabang, ia didorong ke repo yang diberkati dan kartu kanban dipindahkan ke siap untuk ditinjau.

Kemudian, jika cabang diterima oleh ulasan, itu adalah kandidat untuk rilis.

Rilis terjadi ketika satu set cabang yang diterima digabung bersama dan ditandai dengan nomor versi.

Dengan mendorong tag baru ke repo yang diberkati ada kemungkinan basis baru untuk fitur baru.

Untuk menghindari penggabungan konflik, pengembang diminta untuk memperbarui (menggabungkan) cabangnya yang belum dirilis ke tag rilis terbaru.

John Nilsson
sumber
2

Secara pribadi, saya mencoba dan hanya menyimpan kode yang siap dirilis di cabang master.

Ketika saya mengerjakan fitur baru atau perbaikan bug, saya melakukannya di cabang. Saya juga unit-test di cabang. Jika semuanya berjalan dengan baik, barulah saya menggabungkan / mengubah kembali menjadi master.

Saya mencoba dan menggunakan konvensi penamaan cabang umum juga, seperti:

  • bugfix / recursive_loop
  • perbaikan bug / sql_timeout
  • feature / new_layout
  • feature / enhanced_search
xero
sumber