Salah satu keuntungan menggunakan DVCS adalah alur kerja edit-commit-gabungan (lebih dari edit-gabungan-komit sering dipaksakan oleh CVCS). Mengizinkan setiap perubahan unik untuk dicatat dalam repositori independen dari penggabungan memastikan DAG secara akurat mencerminkan silsilah sebenarnya dari proyek.
Mengapa begitu banyak situs web berbicara tentang keinginan untuk "menghindari penggabungan komitmen"? Tidakkah menggabungkan pra-komitmen atau rebound pasca-penggabungan membuat lebih sulit untuk mengisolasi regresi, mengembalikan perubahan di masa lalu, dll?
Titik klarifikasi: Perilaku default untuk DVCS adalah membuat komit gabungan. Mengapa begitu banyak tempat berbicara tentang keinginan untuk melihat sejarah pengembangan linear yang menyembunyikan komitmen gabungan ini?
sumber
git pull
)? Saya bisa melihat mengapa itu bisa bermasalah, tetapi pertanyaan saya adalah tentang semua komitmen gabungan.git pull --rebase == svn up
(longgar-sama dengan, tidak ketat-sama)Jawaban:
Orang ingin menghindari gabungan komitmen karena membuat log lebih cantik. Serius. Sepertinya log terpusat mereka tumbuh dengan, dan secara lokal mereka dapat melakukan semua perkembangan mereka dalam satu cabang. Tidak ada manfaat selain dari estetika itu, dan beberapa kelemahan selain yang Anda sebutkan, seperti membuatnya rawan konflik untuk menarik langsung dari seorang kolega tanpa melalui server "pusat".
sumber
Dalam dua kata:
git bisect
Sejarah linier memungkinkan Anda menentukan sumber bug yang sebenarnya.
Sebuah contoh. Ini adalah kode awal kami:
Cabang 1 melakukan beberapa refactoring sehingga
arg
tidak berlaku lagi:Cabang 2 memiliki fitur baru yang perlu digunakan
arg
:Tidak akan ada konflik penggabungan, namun bug telah diperkenalkan. Untungnya, yang satu ini akan terjebak pada langkah kompilasi, tapi kami tidak selalu beruntung. Jika bug bermanifestasi sebagai perilaku tak terduga, dan bukan kesalahan kompilasi, kami mungkin tidak menemukannya selama satu atau dua minggu. Pada titik itu,
git bisect
untuk menyelamatkan!Oh sial. Inilah yang dilihatnya:
Jadi ketika kami mengirim
git bisect
untuk menemukan komit yang merusak build, itu akan menunjukkan komit gabungan. Yah, itu sedikit membantu, tetapi pada dasarnya menunjuk pada paket komitmen, bukan satu pun. Semua leluhur berwarna hijau. Di sisi lain, dengan rebasing, Anda mendapatkan sejarah linier:Sekarang,
git bisect
akan menunjukkan komit fitur yang tepat yang merusak build. Idealnya, pesan komit akan menjelaskan apa yang dimaksudkan dengan cukup baik untuk melakukan refactor lain dan segera memperbaiki bug.Efeknya hanya diperparah dalam proyek-proyek besar ketika pengelola tidak menulis semua kode, sehingga mereka tidak selalu ingat mengapa komit yang diberikan dilakukan / untuk apa masing-masing cabang. Jadi menunjukkan dengan tepat komit (dan kemudian bisa memeriksa komit di sekitarnya) adalah bantuan besar.
Yang mengatakan, saya (saat ini) masih lebih suka bergabung. Memulihkan kembali ke cabang rilis akan memberi Anda riwayat linier untuk digunakan bersama
git bisect
, sambil mempertahankan riwayat sebenarnya untuk pekerjaan sehari-hari.sumber
gitk --all
sangat berguna (terutama karena saya biasanya memiliki cabang 3-ish pada waktu tertentu, dan beralih di antara mereka setiap hari tergantung pada suasana hati saya di waktu).bisect
hasilnya. Cukup mudah untuk menemukan individu yang berkomitmen denganblame
atau berbedabisect
jika Anda ingin menggali lebih dalam. Dengan riwayat linier, penggabungan dilakukan dari buku, jadi Anda tidak bisa lagi mengatakan penggabungan yang buruk adalah masalahnya. Itu hanya terlihat seperti orang idiot yang menggunakan argumen yang tidak ada, terutama jika argumen itu dihapus beberapa komit sebelumnya. Mencoba mencari tahu mengapa dia melakukan itu jauh lebih sulit ketika Anda menghancurkan sejarah.Singkatnya, karena penggabungan seringkali merupakan tempat lain untuk sesuatu yang salah, dan itu hanya perlu salah sekali untuk membuat orang sangat takut menghadapinya lagi (sekali digigit dua kali malu, jika Anda mau).
Jadi, katakanlah kita sedang mengerjakan Layar Manajemen Akun baru, dan ternyata ada bug yang ditemukan dalam alur kerja Akun Baru. OK, kami mengambil dua jalur terpisah - Anda menyelesaikan Manajemen Akun, dan saya memperbaiki bug dengan Akun Baru. Karena kami berdua berurusan dengan akun, kami telah bekerja dengan kode yang sangat mirip - mungkin kami bahkan harus menyesuaikan potongan kode yang sama.
Sekarang, pada saat ini kami memiliki dua versi perangkat lunak yang berbeda tetapi berfungsi penuh. Kami berdua menjalankan komit pada perubahan kami, kami berdua dengan patuh menguji kode kami, dan secara independen kami sangat yakin kami telah melakukan pekerjaan yang luar biasa. Sekarang apa?
Nah, ini waktunya untuk bergabung, tapi ... sial, apa yang terjadi sekarang? Kita bisa beralih dari dua set perangkat lunak yang berfungsi menjadi satu, perangkat lunak yang baru rusak dan menyatu, di mana Manajemen Akun Anda tidak berfungsi dan Akun Baru rusak dan saya bahkan tidak tahu apakah bug lama masih ada .
Mungkin perangkat lunak itu pintar dan dikatakan ada konflik dan bersikeras kami memberikannya panduan. Nah, sial - Saya duduk untuk melakukannya dan melihat Anda telah menambahkan beberapa kode kompleks yang saya tidak segera mengerti. Saya pikir itu bertentangan dengan perubahan yang saya buat ... Saya bertanya kepada Anda, dan ketika Anda sebentar Anda memeriksa dan Anda melihat kode saya bahwa Anda tidak mengerti. Salah satu atau kami berdua harus meluangkan waktu untuk duduk, melakukan penggabungan yang tepat, dan mungkin menguji ulang seluruh masalah dang untuk memastikan kami tidak mematahkannya.
Sementara itu 8 orang lainnya semua melakukan kode seperti para sadis, saya membuat beberapa perbaikan bug kecil dan mengirimkannya sebelum saya tahu kami memiliki konflik penggabungan, dan pria itu sepertinya waktu yang tepat untuk beristirahat, dan mungkin Anda libur untuk sore atau terjebak dalam rapat atau apa pun. Mungkin sebaiknya aku berlibur saja. Atau berganti karier.
Maka, untuk melepaskan diri dari mimpi buruk ini, beberapa orang menjadi sangat takut pada komitmen (apa lagi yang baru, oke?). Kita tentu saja menolak risiko dalam skenario seperti ini - kecuali kita pikir kita payah dan akan mengacaukannya, dalam hal ini orang mulai bertindak dengan pengabaian yang ceroboh. mendesah
Jadi begitulah. Ya, sistem modern dirancang untuk meringankan rasa sakit ini, dan itu seharusnya dapat dengan mudah mundur dan merendahkan dan merendahkan dan freebase dan hanglide dan semua itu.
Tapi itu semua lebih banyak pekerjaan, dan kami hanya ingin menekan tombol di microwave dan memiliki 4 hidangan sebelum kita punya waktu untuk menemukan garpu, dan semuanya terasa sangat tidak memuaskan - kode berfungsi, produktif, dan bermakna, tetapi anggun menangani penggabungan tidak masuk hitungan.
Programmer, sebagai suatu peraturan, harus mengembangkan memori kerja yang hebat, dan kemudian memiliki kecenderungan untuk segera melupakan semua sampah dan nama variabel dan pelingkupan segera setelah mereka menyelesaikan masalah, dan menangani konflik gabungan (atau lebih buruk, suatu salah menangani penggabungan) adalah undangan untuk diingatkan akan kefanaan Anda.
sumber
Rebasing menyediakan titik cabang bergerak yang menyederhanakan proses mendorong perubahan kembali ke garis dasar. Ini memungkinkan Anda untuk memperlakukan cabang yang sudah berjalan lama seolah-olah itu adalah perubahan lokal. Tanpa rebasing, cabang mengakumulasikan perubahan dari baseline yang akan dimasukkan dalam perubahan yang digabung kembali ke baseline.
Penggabungan meninggalkan garis dasar Anda di titik cabang asli. Jika Anda menggabungkan perubahan beberapa minggu dari garis tempat Anda bercabang, sekarang Anda memiliki banyak perubahan dari titik cabang Anda, banyak di antaranya akan berada di baseline Anda. Ini membuatnya sulit untuk mengidentifikasi perubahan Anda di cabang Anda. Mendorong perubahan kembali ke garis dasar dapat menghasilkan konflik yang tidak terkait dengan perubahan Anda. Dalam kasus konflik, dimungkinkan untuk mendorong perubahan yang tidak konsisten. Penggabungan yang sedang berlangsung membutuhkan upaya untuk mengelola, dan relatif mudah untuk kehilangan perubahan.
Rebase memindahkan titik cabang Anda ke revisi terbaru pada baseline Anda. Setiap konflik yang Anda temui hanya untuk perubahan Anda saja. Mendorong perubahan jauh lebih sederhana. Konflik ditangani di cabang lokal dengan melakukan rebase tambahan. Dalam hal dorongan yang saling bertentangan, yang terakhir untuk mendorong perubahan mereka perlu menyelesaikan masalah dengan perubahan mereka.
sumber
Alat otomatis menjadi lebih baik dalam memastikan bahwa kode penggabungan akan dikompilasi dan dijalankan, sehingga menghindari konflik sintaksis , tetapi mereka tidak dapat menjamin tidak adanya konflik logis yang dapat diperkenalkan oleh penggabungan. Jadi gabungan yang 'berhasil' memberi Anda rasa percaya diri yang salah, padahal kenyataannya itu tidak menjamin apa pun, dan Anda harus mengulang semua pengujian Anda.
Masalah sebenarnya dengan percabangan dan penggabungan, seperti yang saya lihat, adalah menendang pepatah di jalan. Ini memungkinkan Anda mengatakan "Saya hanya akan bekerja di dunia kecil saya sendiri" selama seminggu, dan menangani masalah apa pun yang muncul kemudian. Tetapi memperbaiki bug selalu lebih cepat / lebih murah saat masih segar. Pada saat semua cabang kode mulai digabung, Anda mungkin sudah lupa beberapa nuansa dari hal-hal yang dilakukan.
Ambil kedua masalah tersebut bersama-sama, dan Anda mungkin menemukan diri Anda dalam situasi di mana lebih mudah dan lebih mudah untuk membuat semua orang bekerja di bagasi yang sama dan terus menyelesaikan konflik saat mereka muncul, bahkan jika mereka membuat pengembangan aktif sedikit lebih lambat.
sumber
Poin tambahan yang relevan adalah ini: Dengan rebasing saya dapat dengan mudah memilih atau mengembalikan fitur di cabang rilis saya.
sumber
git cherry-pick -x <commit>
untuk menerapkannya ke cabang rilis. Atau, kami mungkin ingin membatalkan sesuatu untuk rilis, dengangit revert <commit>
. Jika<commit>
gabungan, itu menjadi berbulu. Hal ini mungkin sejauh yang saya tahu, tapi tidak mudah dilakukan. Saat menggunakan rebase, setiap 'penggabungan' adalah satu raksasa tapi komit reguler, mudah dipilih dan dikembalikan.Tiga hal belum dikatakan dalam salah satu jawaban:
Diffing di dalam cabang:
Menggabungkan satu item sekaligus:
Pembersihan sebelum mendorong:
sumber