- Conventional Commits mencoba memberi makna pada pesan commit dengan format
<type>[optional scope]: <description>, tetapi menaruh jenis perubahan di depan dan menjadikan cakupan sebagai opsi, sehingga informasi yang dibutuhkan untuk penelusuran nyata justru terdorong ke belakang
- Kontributor, debugger, dan penangan insiden mencari area kode yang tersentuh perubahan di log commit, dan karena bug dapat muncul dari jenis perubahan apa pun, scope lebih penting daripada type
- Seperti pada
fix(compiler): prevent namespaced SVG <style> elements from being stripped, sifat perbaikan bug sudah bisa dipahami hanya dari deskripsinya, dan seperti pada refactor(core): Update webmcp support to use document.modelContext, satu commit dapat sekaligus mencakup perbaikan, refaktor, dan penambahan fitur, sehingga type menjadi redundan dan membatasi
- Pembuatan CHANGELOG otomatis dan penentuan kenaikan versi semantik bermasalah karena pembaca log commit dan changelog berbeda, dan hasilnya bisa meleset akibat revert, kerusakan kompatibilitas ke belakang yang tidak disengaja, atau kerusakan yang baru diselesaikan belakangan
- Pesan commit dengan prefiks scope menampilkan subjek perubahan terlebih dahulu, dan kondisi build/deploy juga lebih baik didasarkan pada file yang berubah melalui
git diff daripada jenis pada judul
Prioritas yang keliru
- Conventional Commits bertujuan memberi makna pada pesan commit agar pengembang dan pengguna akhir bisa memahami perubahan
<type>[optional scope]: <description>
[optional body]
[optional footer(s)]
- Baris judul terdiri dari
<type> seperti fix, feat, chore, docs, refactor, scope opsional, dan description
- Cacat utamanya adalah struktur yang memprioritaskan type, yakni jenis perubahan, daripada scope, yaitu subjek perubahan
- Struktur yang menjadikan scope opsional memungkinkan informasi terpenting dalam commit hilang, dan menaruh type di paling depan judul membalik prioritas yang seharusnya
Mengapa scope lebih penting daripada type
- Kontributor membaca log commit untuk mencari perubahan sejak kontribusi terakhir, alur keseluruhan proyek, dan commit yang bisa bertabrakan dengan pekerjaan yang sedang berlangsung saat pull atau rebase
- Debugger mencari perubahan yang menyentuh area terkait komponen tempat bug muncul, dan karena bug bisa timbul dari perubahan dengan type apa pun, informasi type tidak membantu
- Penangan insiden menelusuri log commit di sekitar waktu insiden untuk menemukan area penyebab masalah; jika ada commit dengan scope
auth di titik lonjakan error API inbound, itu menjadi kandidat penyebab yang kuat
- Bagi pembaca log commit, informasi penting bukanlah perubahan itu termasuk jenis apa, melainkan area mana yang disentuh
Redundansi dan keterbatasan type
Batas janji otomatisasi
- Gagasan membuat CHANGELOG otomatis dari commit dengan alat seperti git-cliff atau conventional-changelog punya masalah karena pembaca log commit dan changelog berbeda
- CHANGELOG ditujukan untuk pengguna dan berfokus pada pemahaman perbedaan fungsional dan bisnis antarversi
- Log commit ditujukan untuk pengembang dan berfokus pada bagaimana codebase berubah seiring waktu serta alurnya dari sudut pandang scope
- Pada proyek dengan kompleksitas menengah ke atas, satu fitur yang bermakna sering masuk melalui beberapa commit; bagi pengembang proses implementasinya berguna, tetapi bagi pengguna akhir yang penting hanya fitur barunya
- Commit revert penting bagi pengembang dalam alur log commit, tetapi bagi pengguna akhir, perubahan yang sudah dibatalkan sama saja dengan perubahan yang tidak pernah dibuat
- Kenaikan versi semantik berbasis type commit bisa menimbulkan masalah seperti menaikkan major version padahal perubahan yang merusak kompatibilitas ke belakang sudah direvert, salah menaikkan sebagai minor/patch karena kerusakannya baru disadari belakangan, atau dianggap breaking padahal efeknya hilang setelah digabung dengan commit lanjutan
- Dalam situasi seperti ini, histori memang bisa diperbaiki dengan rebase, tetapi workflow bisa mencegah atau merusaknya, dan menurunkan keandalan alur yang disampaikan log commit
- Jika proses build/deploy dipicu oleh type pada judul commit, alat otomatis dapat dilewati, misalnya dengan commit berjudul
docs: fix typos yang ternyata memasukkan kerentanan ke subsistem autentikasi
- Kondisi build/deploy lebih baik ditentukan dengan mengidentifikasi file yang berubah melalui
git diff daripada dari judul commit
Masalah penerapan dan alternatif
- Conventional Commits memang mendorong proyek mendefinisikan himpunan type sendiri, tetapi banyak proyek hanya memakai type bawaan commitlint, yang bisa jadi tidak cocok dengan karakteristik proyek masing-masing
- Spesifikasi Conventional Commits secara teknis hanya mendefinisikan
fix dan feat, sementara type tambahan diserahkan ke masing-masing proyek
- Di lingkungan perusahaan, kebutuhan manajemen perubahan dan audit kadang mewajibkan semua pesan commit memuat nomor tiket; jika
<scope> dipakai untuk nomor tiket, metadata yang berguna pun hilang
- Linux, FreeBSD, Git, Go, NixOS, dan Node.js menggunakan pesan commit dengan prefiks scope yang sesuai dengan proyeknya
- Dalam kernel Linux, scope yang alami adalah subsystem; dalam proyek Go, package path; dan dalam arsitektur microservice, nama microservice
- scopedcommits.com mengusung kembalinya format pesan commit yang berpusat pada scope serta pemisahan antara pembuatan CHANGELOG dan pengelolaan log commit
- Kelebihan Conventional Commits tidak berujung pada manfaat nyata, dan popularitasnya di proyek open source serta kecenderungan AI menjadikannya pilihan default telah mendorong penyebaran pesan commit yang bercampur dengan antipola
1 komentar
Pendapat di Lobste.rs
Senang melihat tulisan yang merangkum sanggahan terhadap conventional commits dengan logika, bukan sekadar penolakan spontan
Saya sendiri tidak pernah terlalu dalam memikirkan kenapa saya tidak suka, dan sempat mengira mungkin karena saya mulai mengaitkannya dengan kode yang dihasilkan LLM. Yang paling saya benci terutama
chore:, dan saya berharap kita tidak perlu menemukan ulang notasi Hungaria. Seharusnya itu memang tidak pernah perlu dibuat sejak awalchore:bahkan sudah tidak ada lagi di panduan gaya commit Angular, mungkin karena mereka sadar istilah itu terlalu ambigu sehingga diserap kebuild:Bahkan saat masih ada di gaya Angular, penjelasan
chore:sebenarnya memberi contoh penggunaan yang cukup spesifik, tetapi di beberapa proyek open source tampaknya label itu dipakai berdasarkan suasana hati untuk pekerjaan yang terasa seperti sesuatu yang malas dijelaskanSaya tidak suka conventional commits, tetapi alternatif yang diusulkan tampaknya melewatkan alasan scope bersifat opsional
Pada proyek kecil yang tidak punya banyak modul yang jelas, konsep “scope” tidak terlalu berguna. Praktik berguna lain yang luput dari keduanya adalah memasukkan nomor isu atau tiket di judul commit; ini memudahkan memahami konteks tambahan dari perubahan dan sangat membantu saat code review. Meski begitu, saya tidak suka jika nomor tiket diwajibkan, karena itu akan menghasilkan banyak tiket tak berguna untuk perubahan kecil; tetapi jika suatu perubahan menangani bug atau pekerjaan tertentu, maka perubahan itu memang seharusnya terhubung ke bug atau pekerjaan tersebut
Itu tetap lebih baik daripada “type” commit yang berulang dan seharusnya sudah terlihat hanya dari baris judul
Jika perubahan jelas berkorespondensi dengan tiket, pakailah commit “nomor tiket”; kalau tidak, gunakan cara lain. Ada perubahan yang lebih cocok ke type tetapi kurang cocok ke scope, dan sebaliknya, jadi scoped commits dan conventional commits pun bisa dicampur
Saya ingin bilang, “jangan gunakan font monospace untuk teks paragraf”
Meski begitu, saya pada umumnya setuju dengan premis tulisannya
Walaupun pesan commit kurang bagus, untuk memahami kira-kira cakupan perubahan saya merekomendasikan sering memakai
git log --name-onlyataugit log --statDengan melihat nama file, kita cukup terbantu untuk tahu apa yang berubah tanpa harus membuka setiap commit satu per satu
Cara yang benar-benar saya sukai adalah memaksa gaya conventional commit pada judul PR
Judul PR masih bisa diedit maintainer setelah merge, tidak perlu menulis ulang riwayat commit, dan jika dipakai bersama alat seperti release-drafter, kita bisa mengotomatiskan changelog yang bermakna di rilis GitHub. Ini memberi tingkat perincian yang sesuai untuk para pemangku kepentingan seperti yang disebut penulis, yaitu memisahkan fitur, perbaikan, dan breaking change, serta otomatis menangani semver yang masuk akal untuk draf rilis GitHub berikutnya
Kritik penulis bahwa komponen seperti
parse-libtidak seharusnya opsional itu benar, dan saya juga setuju bahwa memaksa conventional commits bisa mengintimidasi kontributor baru. Namun, alternatif yang diajukan juga tidak benar-benar lebih baikMeski begitu, penanda breaking change seperti
fix!(parse-lib): Don't leave sparse holes when parsing JSON arraysmemang menyampaikan cukup banyak informasi. Itu menunjukkan bahwa ini adalah perbaikan bug pada komponen tertentu, bahwa perbaikan itu secara tak terelakkan membawa breaking change, dan mengandung makna seperti kenaikan semver minor. Hal seperti ini bisa dipakai di judul PRSaya mengakui saya terlalu terpikat pada conventional commits sebagai cara mendorong disiplin commit, dan akhirnya itu menjadi kebiasaan
Sekarang saya sering merasa itu membatasi dan sewenang-wenang. Di beberapa proyek saya bahkan tidak tahu apakah itu benar-benar kebiasaan yang nyata, dan saya jadi lebih mendekati gaya Linux/Go/Node; pada monorepo dengan beragam konfigurasi, menulis
[service]: [what changed]terasa lebih alami daripada memaksakan type. Ke depan, saya ingin lebih bereksperimen dengan gaya commit pribadi berdasarkan apa yang tampak berguna, alih-alih menyesuaikan diri dengan konvensi yang kaku, dan scoped commits terasa seperti titik awal yang baguschore(lobsters): add my 2 cents on conventionals commits [JIRA-69420]Saya setuju dengan hampir semuanya, tetapi ada satu hal yang saya lihat berbeda dari bagian “memperlihatkan kepada kontributor catatan revisionis yang menurunkan keandalan cerita yang disampaikan log commit”. Penulis tampaknya terutama berbicara tentang branch publik, dan untuk branch publik itu nasihat yang masuk akal. Namun, itu seharusnya tidak berlaku untuk branch privat. Yang penting adalah memudahkan orang yang meninjau perubahan akhir—yakni maintainer, atau diri saya sendiri 10 tahun kemudian—untuk memahaminya; tidak perlu meninggalkan alur pikir yang semrawut, atau yang lebih buruk, serangkaian commit
address reviewJawaban untuk “mengapa scope bersifat opsional?” adalah karena pada proyek kecil seluruh proyek itulah scope-nya
Saya setuju bahwa “type” commit tidak terlalu berguna, tetapi saya juga kurang yakin ada perbedaan besar antara scoped commits dan conventional commits. Scoped pada dasarnya hanyalah conventional tanpa “type”, dan pembedaan seperti fix, feat, refactor, chore tetap merupakan pembedaan yang lumayan
Jika semua orang hanya mengambil default commitlint apa adanya, bukankah yang perlu dilakukan adalah membuat orang lebih mampu menggunakannya?