Mengapa setiap repo Github serius yang saya lakukan menarik permintaan untuk ingin saya menekan komitmen saya menjadi satu komit?
Saya pikir log git ada di sana sehingga Anda dapat memeriksa semua sejarah Anda dan melihat dengan tepat perubahan apa yang terjadi di mana, tetapi menekannya menariknya keluar dari sejarah dan menggabungkannya menjadi satu komit. Apa intinya?
Ini juga tampaknya bertentangan dengan mantra "komit lebih awal dan komit sering".
Jawaban:
Sehingga Anda memiliki sejarah git yang jelas dan ringkas yang dengan jelas dan mudah mendokumentasikan perubahan yang dilakukan dan alasannya.
Sebagai contoh, sebuah log git 'unsquashed' untuk saya mungkin terlihat seperti berikut:
Berantakan sekali!
Sedangkan git log yang dikelola dan digabung dengan lebih hati-hati dengan sedikit fokus tambahan pada pesan untuk ini mungkin terlihat seperti:
Saya pikir Anda dapat melihat titik squashing melakukan secara umum dan prinsip yang sama berlaku untuk menarik permintaan - Keterbacaan Sejarah. Anda juga dapat menambahkan ke log komit yang sudah memiliki ratusan atau bahkan ribuan komit dan ini akan membantu menjaga sejarah yang berkembang singkat dan singkat.
Anda ingin melakukan lebih awal dan sering. Ini praktik terbaik karena berbagai alasan. Saya menemukan bahwa ini menuntun saya untuk sering memiliki komitmen yang "menghapus" (pekerjaan dalam proses) atau "bagian A selesai" atau "kesalahan ketik, perbaikan kecil" di mana saya menggunakan git untuk membantu saya bekerja dan memberi saya poin kerja yang Saya dapat kembali ke jika kode berikut ini tidak berfungsi karena saya maju untuk menyelesaikan pekerjaan. Namun saya tidak perlu atau menginginkan sejarah itu sebagai bagian dari sejarah git akhir sehingga saya dapat menekan komitmen saya - tetapi lihat catatan di bawah ini tentang apa artinya ini pada cabang pengembangan vs master.
Jika ada tonggak utama yang mewakili tahapan kerja yang berbeda, masih ok untuk memiliki lebih dari satu komit per fitur / tugas / bug. Namun ini sering dapat menyoroti fakta bahwa tiket yang sedang dikembangkan adalah 'terlalu besar' dan perlu dipecah menjadi potongan-potongan kecil yang dapat berdiri sendiri, misalnya:
sepertinya "1 karya". Entah mereka ada atau tidak! Sepertinya tidak masuk akal untuk memecahkannya. Namun pengalaman telah menunjukkan kepada saya bahwa (tergantung pada ukuran dan kompleksitas organisasi) jalur yang lebih terperinci adalah:
Potongan kecil berarti ulasan kode yang lebih mudah, pengujian unit yang lebih mudah, kesempatan yang lebih baik untuk qa, penyelarasan yang lebih baik dengan Prinsip Tanggung Jawab Tunggal, dll.
Untuk kepraktisan kapan harus melakukan squash seperti itu, pada dasarnya ada dua tahap berbeda yang memiliki alur kerja sendiri
Selama perkembangan Anda, Anda melakukan pesan 'awal dan sering' dan dengan cepat 'sekali pakai'. Anda mungkin ingin squash di sini kadang-kadang, misalnya terjepit di wip dan todo pesan dilakukan. Tidak masalah, di dalam cabang, untuk mempertahankan beberapa komitmen yang mewakili langkah berbeda yang Anda buat dalam pengembangan. Sebagian besar squash yang Anda pilih harus berada di dalam cabang-cabang fitur ini, sementara mereka sedang dikembangkan dan sebelum bergabung untuk dikuasai.
Saat menambahkan ke cabang jalur utama, Anda ingin komit dibuat ringkas dan diformat dengan benar sesuai dengan riwayat jalur utama yang ada. Ini mungkin termasuk ID sistem Pelacak Tiket, mis. JIRA seperti ditunjukkan dalam contoh. Squashing tidak benar-benar berlaku di sini kecuali jika Anda ingin 'menggulung' beberapa komitmen berbeda pada master. Biasanya tidak.
Menggunakan
--no-ff
saat penggabungan ke master akan menggunakan satu komit untuk penggabungan dan juga mempertahankan sejarah (di cabang). Beberapa organisasi menganggap ini sebagai praktik terbaik. Lihat lebih lanjut di https://stackoverflow.com/q/9069061/631619 Anda juga akan melihat efek praktis digit log
mana--no-ff
komit akan menjadi komit terbaru, di bagian atas KEPALA (bila baru saja selesai), sedangkan tanpanya--no-ff
mungkin lebih jauh dalam sejarah, tergantung pada tanggal dan komitmen lainnya.sumber
Karena seringkali orang yang menarik PR peduli tentang efek bersih dari komit "menambahkan fitur X", bukan tentang "templat dasar, fungsi perbaikan bug X, menambahkan fungsi Y, memperbaiki kesalahan ketik dalam komentar, parameter penskalaan data yang disesuaikan, hashmap berkinerja lebih baik daripada daftar "... level detail
Jika Anda berpikir bahwa 16 komit Anda lebih baik diwakili oleh 2 komit daripada 1 "Fitur tambahan X, faktor ulang Z untuk menggunakan X" maka itu mungkin baik untuk mengusulkan sebuah pr dengan 2 komit, tetapi mungkin lebih baik untuk mengusulkan 2 p terpisah dalam hal itu (jika repo masih bersikeras pada komit tunggal)
Ini tidak bertentangan dengan mantra "komit lebih awal dan komit sering", seperti dalam repo Anda, ketika Anda sedang mengembangkan Anda masih memiliki detail granular, sehingga Anda memiliki peluang minimal kehilangan pekerjaan, dan orang lain dapat meninjau / menarik / mengusulkan pr menentang pekerjaan Anda saat pr baru sedang dikembangkan.
sumber
Alasan utama dari apa yang bisa saya lihat adalah sebagai berikut:
Merge pull request #123 from joebloggs/fix-snafoo
--first-parent
sudut pandang--first-parent
sudut pandang (perhatikan bahwa ini hanya diperbaiki di Git 2.6.2, jadi kami bisa memaafkan GitHub karena tidak memiliki itu tersedia)Jadi, ketika Anda menggabungkan ketiga situasi di atas, Anda mendapatkan situasi di mana komit tanpa ikatan digabung terlihat buruk dari GitHub UI.
Riwayat Anda dengan komit terjepit akan terlihat seperti
Sedangkan tanpa terjepit melakukan sejarah akan terlihat seperti
Ketika Anda memiliki banyak komitmen dalam penelusuran PR di mana perubahan terjadi dapat menjadi sedikit mimpi buruk jika Anda membatasi diri untuk menggunakan GitHub UI .
Misalnya, Anda menemukan penunjuk nol sedang tidak direferensikan di suatu tempat dalam file ... jadi Anda berkata "siapa yang melakukan ini, dan kapan? Versi rilis apa yang terpengaruh?". Kemudian Anda berjalan ke tampilan menyalahkan di UI GitHub dan Anda melihat bahwa garis itu diubah
789fdfffdf
... "oh tapi tunggu sebentar, baris itu baru saja indentasinya diubah agar sesuai dengan sisa kode", jadi sekarang Anda perlu menavigasi ke status pohon untuk file yang di komit induk dan mengunjungi kembali halaman menyalahkan ... akhirnya Anda menemukan komit ... itu komit dari 6 bulan yang lalu ... "oh **** ini dapat mempengaruhi pengguna selama 6 bulan" Anda mengatakan ... ah tapi tunggu, komit itu sebenarnya dalam Permintaan Tarik dan hanya bergabung kemarin dan belum ada yang memotong rilis ... "Sialan kalian untuk menggabungkan komitmen tanpa menekan sejarah" adalah teriakan yang biasanya dapat didengar setelah sekitar 2 atau 3 ekspedisi kode arkeologi melalui GitHub UISekarang mari kita pertimbangkan bagaimana ini bekerja jika Anda menggunakan baris perintah Git (dan super-mengagumkan 2.6.2 yang memiliki perbaikan untuk
git blame --first-parent
)Jadi sejarah komit kita akan terlihat seperti
Tapi kita juga bisa melakukannya
(Dengan kata lain: Git CLI memungkinkan Anda memiliki kue dan memakannya juga)
Sekarang ketika kita menekan masalah null pointer ... well kita hanya menggunakan
git blame --first-parent -w dodgy-file.c
dan kita langsung diberikan komit tepat di mana referensi-nol pointer-nol diperkenalkan ke cabang master mengabaikan perubahan spasi putih sederhana.Tentu saja jika Anda melakukan penggabungan menggunakan GitHub UI maka
git log --first-parent
itu benar-benar jelek berkat GitHub yang memaksa baris pertama dari pesan komit gabungan:Jadi untuk mempersingkat cerita:
GitHub UI (Oktober 2015) memiliki sejumlah kekurangan dengan cara menggabungkan permintaan tarik, bagaimana menyajikan riwayat commit dan bagaimana atributnya menyalahkan informasi. Cara terbaik saat ini untuk meretas cacat-cacat ini di GitHub UI adalah dengan meminta orang untuk menekan komitmen mereka sebelum bergabung.
Git CLI tidak memiliki masalah ini dan Anda dapat dengan mudah memilih tampilan mana yang ingin Anda lihat sehingga Anda berdua dapat menemukan alasan mengapa perubahan tertentu dibuat seperti itu (dengan melihat riwayat dari komitmen yang tidak dirusak) serta lihat komitmen terjepit.
Tulisan Skrip
Alasan terakhir yang sering dikutip untuk squashing commit adalah untuk membuat backporting lebih mudah ... jika Anda hanya memiliki satu commit untuk mendukung port (yaitu commit squashing) maka mudah untuk memilih ...
Nah jika Anda melihat sejarah git dengan
git log --first-parent
maka Anda bisa saja memilih komit gabungan. Sebagian besar orang bingung menentukan komitmen memilih cherry karena Anda harus menentukan-m N
opsi tetapi jika Anda mendapat komit darigit log --first-parent
maka Anda tahu bahwa itu adalah orang tua pertama yang ingin Anda ikuti sehingga akan menjadigit cherry-pick -m 1 ...
sumber
--first-parent
diri saya untuk memenangkan argumen melawan squashing commit ;-)Saya setuju dengan sentimen yang diungkapkan dalam jawaban lain di utas ini tentang menunjukkan riwayat fitur yang jelas dan ringkas yang ditambahkan dan bug diperbaiki. Namun saya lakukan, ingin membahas aspek lain yang pertanyaan Anda luput tetapi tidak secara eksplisit menyatakan. Bagian dari hangup yang mungkin Anda miliki tentang beberapa metode kerja git adalah git memungkinkan Anda untuk menulis ulang sejarah yang tampaknya aneh ketika diperkenalkan ke git setelah menggunakan bentuk kontrol sumber lain di mana tindakan seperti itu tidak mungkin. Selain itu, ini juga bertentangan dengan prinsip kontrol sumber yang diterima secara umum bahwa sekali sesuatu dilakukan / dicentang ke kontrol sumber, Anda harus dapat kembali ke keadaan itu tidak peduli perubahan apa pun yang Anda lakukan setelah komit itu dilakukan. Seperti yang Anda maksudkan dalam pertanyaan Anda, ini adalah salah satu situasi itu. Saya pikir git adalah sistem kontrol versi yang hebat; namun, untuk memahaminya Anda harus memahami beberapa detail implementasi dan merancang keputusan di baliknya, dan sebagai hasilnya ia memiliki kurva belajar yang lebih curam. Perlu diingat git dimaksudkan untuk menjadi sistem kontrol versi terdistribusi dan itu akan membantu menjelaskan mengapa para desainer mengizinkan sejarah git untuk ditulis ulang dengan squash commit menjadi salah satu contohnya.
sumber
git gc
telah dijalankan untuk membuang objek yang tidak direferensikan.Karena perspektif ... Praktik terbaik adalah memiliki komitmen tunggal per
<<issue-management-system>>
masalah tunggal jika memungkinkan.Anda dapat memiliki banyak komitmen seperti yang Anda inginkan di cabang fitur / repo Anda sendiri, tetapi itu adalah riwayat Anda yang relevan dengan apa yang Anda lakukan sekarang untuk perspektif ANDA ... itu bukan SEJARAH untuk seluruh TIM / PROYEK atau aplikasi dari mereka perspektif untuk disimpan beberapa bulan dari sekarang ...
Jadi setiap kali Anda ingin melakukan perbaikan bug atau fitur untuk repo umum (contoh ini adalah dengan mengembangkan cabang) apa yang bisa Anda lakukan sebagai berikut:
cara rebase cabang fitur Anda menjadi berkembang dengan cepat
sumber
Saya akan melihat apakah kode tersebut go public atau tidak.
Ketika proyek bersifat pribadi:
Saya akan merekomendasikan untuk tidak squash dan melihat pembuatan sosis. Jika Anda menggunakan komit yang baik dan kecil, alat seperti git bisect sangat berguna dan orang-orang dapat dengan cepat menunjukkan komitmen regresi, dan melihat mengapa Anda melakukannya (karena pesan komit).
Ketika proyek go public:
Hancurkan semuanya karena beberapa komit dapat berisi kebocoran keamanan. Misalnya kata sandi yang telah dikomit dan dihapus lagi.
sumber