Tag v1.0.0 di chapter sebelumnya memakai angka tanpa ditanya asalnya. Padahal angka itulah bahasa yang dibaca pengguna: 0.1.0 berarti “coba saja”, 1.0.0 berarti “sudah bisa diandalkan”, 2.0.0 berarti “siap-siap menyesuaikan kode”. Tanpa aturan bersama, angka versi cuma selera — proyek A melompat ke 2.0 karena tambah fitur, proyek B karena mengganti logo. Semantic Versioning (SemVer) menstandarkan makna angka sehingga penomoran bisa dibaca mesin dan manusia. Chapter ini menerapkan aturannya pada riwayat tag proyek kasir kecil, termasuk fase pra-rilis dan jebakan urutannya di Git.
Anatomi MAJOR.MINOR.PATCH #
SemVer menomori versi dengan tiga angka:
| Segmen | Nama | Kapan dinaikkan |
|---|---|---|
1 | MAJOR | perubahan yang merusak kompatibilitas — pemakai versi lama harus menyesuaikan |
2 | MINOR | fitur baru yang mundur-kompatibel — pemakai lama tidak apa-apa, ada bonus |
3 | PATCH | perbaikan bug yang mundur-kompatibel — perilaku salah dibetulkan |
Aturan penaikannya bertingkat seperti odometer: perbaikan bug menaikkan PATCH; fitur baru mereset PATCH dan menaikkan MINOR; perubahan merusak mereset keduanya dan menaikkan MAJOR. Contoh nyatanya: memperbaiki salah hitung kembalian di kasir berarti 1.2.0 → 1.2.1; menambah mode diskon member berarti 1.2.1 → 1.3.0; mengubah format struk yang memaksa pelanggan mengganti parser mereka berarti 1.3.0 → 2.0.0.
Riwayat Versi Sebuah Proyek Kecil #
Aturan itu paling jelas dilihat sebagai riwayat sungguhan. Kita bangun layar kasir sederhana dan menomori setiap titiknya dengan tag — pra-rilis menyala di tengah jalan, lalu stabilisasi dan perubahan besar menutupnya:
mkdir latihan-semver && cd latihan-semver
git init -b main
git config user.name "Budi Santoso"
git config user.email "[email protected]"
printf 'total belanja: 0\n' > kasir.md
git add kasir.md
git commit -m "Buat layar kasir dasar"
git tag 0.1.0
printf 'total belanja: 0\ndiskon member: 10 persen\n' > kasir.md
git add kasir.md
git commit -m "Tambah hitung diskon member"
git tag 0.2.0
printf 'total belanja: 0\ndiskon member: 10 persen\nkembalian dihitung dari total\n' > kasir.md
git add kasir.md
git commit -m "Perbaiki salah hitung kembalian"
git tag 0.2.1
printf 'total belanja: 0\ndiskon member: 10 persen\nkembalian dihitung dari total\nstruk: siap\n' > kasir.md
git add kasir.md
git commit -m "Susun kandidat alpha tampilan struk"
git tag 1.0.0-alpha
printf 'total belanja: 0\ndiskon member: 10 persen\nkembalian dihitung dari total\nstruk: rapi\n' > kasir.md
git add kasir.md
git commit -m "Rapikan tampilan diskon untuk beta"
git tag 1.0.0-beta
printf 'total belanja: 0\ndiskon member: 10 persen\nkembalian dihitung dari total\nstruk: final\n' > kasir.md
git add kasir.md
git commit -m "Kandidat rilis akhir 1.0.0"
git tag 1.0.0-rc.1
printf '# Kasir Toko\ntotal belanja: 0\ndiskon member: 10 persen\nkembalian: otomatis\nstruk: final\n' > kasir.md
git add kasir.md
git commit -m "Rilis stabil 1.0.0"
git tag 1.0.0
printf '# Kasir Toku\ntotal: 0\ndiskon: 10%%\nkembalian: otomatis\nstruk: final\n' > kasir.md
git add kasir.md
git commit -m "Ubah format struk tidak kompatibel"
git tag 2.0.0Delapan commit, delapan tag. Riwayat lengkapnya terbaca sekali jalan:
git log --oneline --decorateOutput yang Dihasilkan:
67a02cf (HEAD -> main, tag: 2.0.0) Ubah format struk tidak kompatibel
692f611 (tag: 1.0.0) Rilis stabil 1.0.0
69368bd (tag: 1.0.0-rc.1) Kandidat rilis akhir 1.0.0
386dd7d (tag: 1.0.0-beta) Rapikan tampilan diskon untuk beta
3dff346 (tag: 1.0.0-alpha) Susun kandidat alpha tampilan struk
9692108 (tag: 0.2.1) Perbaiki salah hitung kembalian
e9c7763 (tag: 0.2.0) Tambah hitung diskon member
3fb4fb6 (tag: 0.1.0) Buat layar kasir dasarAlasan setiap loncatannya diringkas berikut — persis narasi yang tidak bisa ditulis ulang dari angka saja:
| Loncatan | Segmen naik | Alasan |
|---|---|---|
0.1.0 → 0.2.0 | MINOR | fitur baru: hitung diskon member |
0.2.0 → 0.2.1 | PATCH | perbaikan bug: salah hitung kembalian |
0.2.1 → 1.0.0 | MAJOR | deklarasi stabil: kontrak publik ditetapkan |
1.0.0 → 2.0.0 | MAJOR | format struk berubah, kompatibilitas rusak |
Fase 0.x: Masih Mencari Bentuk #
Versi 0.1.0 sampai 0.2.1 sengaja belum menyentuh 1.0.0. SemVer menyebut fase awal ini khusus: selama MAJOR bernilai 0, apapun boleh berubah kapan pun — penomoran 0.x adalah pengumuman “jangan bergantung pada saya dulu”. Naik dari 0.x ke 1.0.0 bukan fitur baru, melainkan komitmen: mulai titik itu setiap perubahan merusak akan dibayar kenaikan MAJOR, dan pengguna berhak protes bila janji itu dilanggar. Karena itu rilis 1.0.0 biasanya menyertai peristiwa stabil — API dibekukan, dokumentasi tuntas, atau pengguna pertama di luar tim.
Fase Pra-rilis: alpha, beta, rc #
Tiga tag di tengah riwayat tadi — 1.0.0-alpha, 1.0.0-beta, 1.0.0-rc.1 — adalah penanda pra-rilis: alpha (fungsi inti baru jadi), beta (siap diuji orang luar), rc (release candidate — kandidat final menunggu persetujuan). SemVer menetapkan urutan naik: alpha dulu, lalu beta, lalu rc, dan versi final berdiri paling akhir — pra-rilis selalu lebih rendah dari rilisnya. Mari saring daftar tag pada keluarga 1.0.0:
git tag -l "1.0.0*"Output yang Dihasilkan:
1.0.0
1.0.0-alpha
1.0.0-beta
1.0.0-rc.1Ada yang aneh pada urutan itu: 1.0.0 berdiri sebelum 1.0.0-alpha. Keluaran git tag diurutkan secara alfabetis, dan string yang habis (1.0.0) menang atas yang berlanjut (1.0.0-alpha). Untuk urutan versi yang benar, kita minta Git mengurutkan sebagai versi dengan trik versionsort.suffix:
git -c versionsort.suffix=- tag --sort=v:refname -l "1.0.0*"Output yang Dihasilkan:
1.0.0-alpha
1.0.0-beta
1.0.0-rc.1
1.0.0Urutan kini sesuai SemVer: alpha → beta → rc.1 → final. Opsi versionsort.suffix=- memberi tahu pengurutan bahwa tanda minus menandai akhiran pra-rilis sehingga 1.0.0-alpha diperlakukan lebih rendah daripada 1.0.0. Tanpa konfigurasi itu pengurutan versi Git menempatkan pra-rilis setelah versi finalnya — jebakan yang kerap mengagetkan saat skrip otomatis memilih “versi terbaru”.
Daftar seluruh tag proyek ini memperlihatkan peta lengkapnya:
git tagOutput yang Dihasilkan:
0.1.0
0.2.0
0.2.1
1.0.0
1.0.0-alpha
1.0.0-beta
1.0.0-rc.1
2.0.0Konvensi v pada Nama Tag #
Dua gaya hidup berdampingan: tag 1.0.0 polos atau v1.0.0 berawalan v. SemVer sendiri tidak mengatur awalan — spesifikasinya membicarakan string versi 1.0.0, bukan nama ref. Praktiknya berbagi selera:
| Kegunaan | v-prefix | tanpa v |
|---|---|---|
| Dibaca manusia | jelas menyatakan “versi” | ringkas, murni angka |
Dibaca skrip dari berkas VERSION | perlu dikupas dulu (v dibuang) | langsung terpakai |
| Kebiasaan ekosistem | Git sendiri, banyak proyek C/Go | banyak proyek Ruby/Rust |
Yang menentukan bukan rasa, melainkan konsistensi: campur v1.0.0 dengan 2.0.0, dan pola git tag -l "v1.*" akan kehilangan separuh riwayat. Pilih satu gaya di awal proyek, catat di pedoman kontribusi, dan pertahankan. Materi section ini memakai v pada repo yang meniru rilis publik, dan polos pada latihan SemVer murni — agar keduanya terasa sama-sama wajar.
Penomoran yang disiplin barulah separuh alur rilis. Setelah tahu angka apa yang akan dipakai, tinggal menjalankan rangkaian langkah terstandar dari pembekuan fitur sampai pengumuman — rangkaian itulah yang dirakit di chapter berikutnya: Release Workflow .