Situs toko kita sudah punya riwayat rapi: beranda, katalog, lalu beberapa perbaikan. Suatu hari sebuah pertanyaan muncul: commit mana persisnya yang berisi “katalog pertama kali jadi”? Mengingat hash acak seperti 16ac351 tidak realistis untuk manusia, sementara branch terus melaju meninggalkan commit lama. Git menyediakan mekanisme khusus untuk masalah ini: tag — nama tetap yang menempel pada satu commit dan tidak pernah berpindah. Chapter ini membedah bagaimana tag bekerja di balik layar, mengapa tag berbeda fundamental dari branch, dan kapan tag menjadi alat yang tepat.
Tag adalah Penunjuk Tetap ke Satu Commit #
Di level paling rendah, tag hanyalah berkas kecil berisi satu hash. Kita bangun repository latihan, tandai satu commit, lalu intip isi .git secara langsung:
mkdir latihan-konsep && cd latihan-konsep
git init -b main
git config user.name "Budi Santoso"
git config user.email "[email protected]"
printf '# Toko Berkah\nberanda\n' > situs.md
git add situs.md
git commit -m "Buat beranda toko"
printf 'daftar produk unggulan\n' > katalog.md
git add katalog.md
git commit -m "Tambah halaman katalog"
git tag v1.0.0Perintah git tag v1.0.0 berjalan sunyi tanpa keluaran — tag dibuat pada commit yang sedang menjadi HEAD. Isinya bisa dibuktikan langsung dengan membaca berkas ref-nya:
cat .git/refs/tags/v1.0.0Output yang Dihasilkan:
16ac351ebc9ad6c2d9bc206a3aedeced413d6d5ecat .git/refs/heads/mainOutput yang Dihasilkan:
16ac351ebc9ad6c2d9bc206a3aedeced413d6d5eKedua berkas berisi hash yang sama: 16ac351 — commit “Tambah halaman katalog”. Hash itu dihitung dari isi commit sehingga nilainya berbeda di mesin pembaca; yang penting justru kesamaan kedua nilai itu. Tag lightweight seperti ini benar-benar cuma penunjuk: tidak ada objek tambahan, tidak ada pesan, hanya satu baris hash.
Branch Bergerak, Tag Diam #
Perbedaan mendasah dengan branch baru terasa ketika commit baru datang. Kita tambahkan dua commit lagi:
printf '# Toko Berkah\nberanda\nmenu: beranda | katalog\n' > situs.md
git add situs.md
git commit -m "Perbaiki menu navigasi"
printf '[email protected]\n' > kontak.md
git add kontak.md
git commit -m "Tambah halaman kontak"Kini kita baca ulang kedua berkas ref yang tadi:
cat .git/refs/heads/mainOutput yang Dihasilkan:
23052964548660e688d68cedca8b9c98c17cc2b8cat .git/refs/tags/v1.0.0Output yang Dihasilkan:
16ac351ebc9ad6c2d9bc206a3aedeced413d6d5eBerkas main berpindah ke 2305296 (commit terbaru), sedangkan v1.0.0 masih menempel pada 16ac351 — persis seperti saat dibuat. Perilaku ini bukan kebetulan: Git menggeser refs/heads/main setiap kali commit baru dibuat di branch itu, tetapi tidak pernah menyentuh refs/tags/* atas inisiatifnya sendiri. Hasilnya terlihat dari kedua sisi:
git rev-parse mainOutput yang Dihasilkan:
23052964548660e688d68cedca8b9c98c17cc2b8git rev-parse v1.0.0Output yang Dihasilkan:
16ac351ebc9ad6c2d9bc206a3aedeced413d6d5eSkema berikut merangkum hubungan itu pada repository kita:
Pada diagram, tag dan branch sama-sama menunjuk ke commit, tetapi hanya main yang panahnya bergeser ke kanan setiap ada commit baru. git log --oneline --decorate memperlihatkan keadaan akhirnya:
git log --oneline --decorate --allOutput yang Dihasilkan:
2305296 (HEAD -> main) Tambah halaman kontak
5b6986a Perbaiki menu navigasi
16ac351 (tag: v1.0.0) Tambah halaman katalog
089d8d9 Buat beranda tokoBaris 16ac351 (tag: v1.0.0) tetap diam di tengah riwayat sementara HEAD -> main terus berada di ujung. Mekanisme penunjuk ber-hash ini adalah kelanjutan dari pembahasan Commit Hash dan References
; tag hanyalah salah satu penghuni namespace ref.
Namespace refs/tags/ #
Git menyimpan seluruh penunjuk di bawah .git/refs/ yang terbagi per jenis:
ls .git/refsOutput yang Dihasilkan:
heads
tagsls .git/refs/tagsOutput yang Dihasilkan:
v1.0.0Direktori heads/ menampung branch lokal dan tags/ menampung tag — keduanya hidup berdampingan tanpa saling menimpa nama, jadi tag v1.0.0 dan branch v1.0.0 bisa eksis bersamaan. Konsekuensi praktisnya: tag tidak pernah muncul di daftar branch.
git branchOutput yang Dihasilkan:
* mainMeskipun v1.0.0 sudah dibuat, git branch hanya melaporkan main. Pemisahan namespace ini pula yang membuat perintah git push origin v1.0.0 tahu harus mengirim ref tag, bukan branch — detail yang dibedah tuntas di chapter Berbagi Tag ke Remote
.
Tag untuk Titik Penting #
Kegunaan utama tag adalah memberi nama pada commit penting. Dua kasus paling umum:
- Rilis:
v1.0.0,v2.3.1— commit yang dikirim ke pengguna. Tag menjadi jawaban presisi untuk “versi 2.3.1 dibangun dari commit mana?” - Checkpoint:
eksperimen-berhasil,demo-klien-2026— titik yang ingin dirujuk cepat tanpa harus mengingat hash, misalnya batas sebelum refactor besar.
Karena tidak bergerak, tag aman dirujuk jauh setelah dibuat: git checkout v1.0.0, git diff v1.0.0..main, atau git log v1.0.0.. akan membaca titik yang sama berapa kali pun perintah itu diulang. Inilah fondasi seluruh alur rilis di section ini — dari Semantic Versioning
sampai Release Workflow
.
Tag Bukan Branch Rilis #
Praktik branch release/1.0 yang dibahas di Strategi Branching
sering disamakan dengan tag, padahal keduanya berbeda filosofi. Branch rilis adalah garis pengembangan yang tetap menerima commit perbaikan — branch itu hidup dan bergerak. Tag adalah potret satu titik pada satu waktu — sekali dicap, anggap selesai. Skenario singkat perbandingannya:
| Aspek | Branch release/1.0 | Tag v1.0.0 |
|---|---|---|
| Menunjuk ke | commit terbaru branch (bergerak) | satu commit tetap |
| Menerima commit | ya, misalnya perbaikan hotfix | tidak pernah |
| Kegunaan | merawat versi yang beredar | menandai versi yang dirilis |
| Pasangan ideal | dipotret dengan tag tiap rilis | — |
Dalam praktik keduanya bersahabat: branch release/1.0 merawat perbaikan, lalu setiap titik rilis dari branch itu dipotret sebagai tag v1.0.1, v1.0.2, dan seterusnya.
Satu hal belum kita bahas: git tag v1.0.0 barusan membuat jenis tag paling sederhana. Ada jenis kedua yang menyimpan pesan, penanda waktu, dan nama pembuat sebagai objek penuh di database Git. Perbedaan keduanya menentukan pilihan pada tiap rilis nyata — itulah dua chapter berikutnya, dimulai dari Lightweight Tag
.