Tag v1.0.0 di komputer kita belum berarti apa-apa bagi dunia — rilis baru sungguhan ketika rekan dan pengguna bisa mengambilnya. Kebiasaan dari section Remote Repository membuat kita menduga git push akan membawa serta tag, apalagi tag itu menempel di commit yang memang dikirim. Dugaan itu keliru: Git sengaja tidak mengirim tag pada git push biasa. Chapter ini membuktikannya di sandbox, lalu menempuh jalur-jalur resmi untuk mengirim, menarik, dan menghapus tag di remote — semuanya dengan remote lokal tanpa jaringan.

Menyiapkan Remote Latihan #

Pola sandboxnya sama seperti membahas push dulu: repository kerja berisi tiga commit dengan dua tag, plus satu bare repository sebagai imitasi server:

bash
mkdir latihan-remote && cd latihan-remote
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"
printf 'daftar produk unggulan terbaru\n' > katalog.md
git add katalog.md
git commit -m "Perbaiki judul katalog"
git tag v0.1.0 HEAD~1
git tag -a v1.0.0 -m "Rilis katalog pertama"
git init --bare ../toko-rilis.git
git remote add origin ../toko-rilis.git

Bare repository toko-rilis.git hanya berisi database tanpa working directory — persis perilaku server Git; jalurnya sengaja relatif supaya keluaran rapi.

Bukti: git push Tidak Membawa Tag #

Kita kirim branch main seperti biasa:

bash
git push -u origin main

Output yang Dihasilkan:

text
To ../toko-rilis.git
 * [new branch]      main -> main
branch 'main' set up to track 'origin/main'.

Branch terkirim, tracking terpasang. Bagaimana dengan tagnya? Interogasi paling langsung adalah menanyakan isi remote dari luar — git ls-remote --tags membaca daftar ref tag di remote tanpa menyentuh repository lokal:

bash
git ls-remote --tags origin

Perintah itu sunyi tanpa keluaran — remote tidak menyimpan satu pun tag meskipun v0.1.0 dan v1.0.0 ada di lokal dan menempel di commit yang barusan terkirim. Perilaku ini disengaja: tag rilis menyentuh publik, jadi Git memaksa keputusan eksplisit mana tag yang dibagikan, alih-alih membocorkannya diam-diam tiap kali push.

Mengirim Tag Satu per Satu #

Bentuk eksplisit pertama: sebutkan nama tag sebagai refspec push, seperti mengirim branch:

bash
git push origin v1.0.0

Output yang Dihasilkan:

text
To ../toko-rilis.git
 * [new tag]         v1.0.0 -> v1.0.0

Baris * [new tag] v1.0.0 -> v1.0.0 mengonfirmasi ref tag dibuat di remote. Bentuk ini cocok untuk rilis: satu nama, satu keputusan sadar. Sintaks refspec penuh git push origin refs/tags/v1.0.0 juga sah — nama polos seperti di atas hanyalah bentuk pendeknya.

Mengirim Semua Tag Sekaligus #

Saat banyak tag menumpuk — misalnya mengarsipkan proyek lama ke remote baru — opsi --tags mengirim seluruh ref di namespace refs/tags/:

bash
git push origin --tags

Output yang Dihasilkan:

text
To ../toko-rilis.git
 * [new tag]         v0.1.0 -> v0.1.0

Yang tersisa di lokal hanyalah v0.1.0, dan memang dialah yang terkirim. Setelahnya, kondisi remote bisa dibaca ulang:

bash
git ls-remote --tags origin

Output yang Dihasilkan:

text
a4bb963420dcf205f71f092001448ebdbcd7320d	refs/tags/v0.1.0
4ec166d3b3f6b2349c9a32e85f5741994141d639	refs/tags/v1.0.0
d987eb2818ecd11b750962516f4914abbf73c9e5	refs/tags/v1.0.0^{}

Tiga baris itu layak dibedah pelan-pelan. Kolom kiri adalah hash yang ditunjuk tiap ref, dipisah TAB dari nama ref di kolom kanan. refs/tags/v0.1.0 menunjuk a4bb963 — lightweight, langsung ke commit. refs/tags/v1.0.0 menunjuk 4ec166d — objek tag. Baris ketiga refs/tags/v1.0.0^{} adalah baris peeled (“dikupas”): ls-remote ikut melaporkan hash commit yang berada di balik objek tag, ditandai akhiran ^{}. Dua baris terakhir itu satu paket informasi tentang satu tag annotated. Hash pada keluaran ini milik sandbox — di mesin pembaca nilainya berbeda, tetapi struktur barisnya sama.

Clone dan fetch Membawa Tag #

Sisi penerima lebih ramah: git clone mengunduh seluruh tag secara otomatis. Kita klone dari sisi lain:

bash
cd .. && git clone toko-rilis.git klon-toko

Output yang Dihasilkan:

text
Cloning into 'klon-toko'...
done.
bash
cd klon-toko && git tag

Output yang Dihasilkan:

text
v0.1.0
v1.0.0

Kedua tag hadir di klone tanpa perintah tambahan. Nah, bagaimana bila tag baru lahir setelah klone dibuat? Di repository asal kita tambahkan commit beserta tag v1.1.0, lalu mengirimkannya:

bash
cd ../latihan-remote
printf '[email protected]\n' > kontak.md
git add kontak.md
git commit -m "Tambah halaman kontak"
git tag -a v1.1.0 -m "Rilis halaman kontak"
git push origin v1.1.0

Output yang Dihasilkan:

text
To ../toko-rilis.git
 * [new tag]         v1.1.0 -> v1.1.0

Di klone, git fetch --tags menarik tag dari remote:

bash
cd ../klon-toko && git fetch --tags

Output yang Dihasilkan:

text
From ../toko-rilis
 * [new tag]         v1.1.0     -> v1.1.0

Baris * [new tag] v1.1.0 -> v1.1.0 menandai tag tiba. Daftar tag di klone kini lengkap:

bash
git tag

Output yang Dihasilkan:

text
v0.1.0
v1.0.0
v1.1.0

Perhatikan bahwa baris keluaran fetch tidak memuat pembaruan branch — main di klone tetap di posisi lama karena yang terkirim memang hanya tag. Mekanisme fetch --tags mengambil seluruh refspec refs/tags/*:refs/tags/* tanpa peduli tag menempel di commit mana pun.

Menghapus Tag di Remote #

Penanda coba-coba yang salah kirim perlu ditarik kembali. git push dengan opsi --delete menghapus ref tag di remote:

bash
cd ../latihan-remote && git push origin --delete v0.1.0

Output yang Dihasilkan:

text
To ../toko-rilis.git
 - [deleted]         v0.1.0

Baris - [deleted] v0.1.0 mengonfirmasi ref tag dihapus dari toko-rilis.git — formatnya sama seperti penghapusan branch remote di Menghapus Remote Branch . Perbedaan pentingnya: tag v0.1.0 di repository lokal tetap ada; yang terhapus hanya salinan remote. Kondisi akhir remote terbaca dari ls-remote:

bash
git ls-remote --tags origin

Output yang Dihasilkan:

text
4ec166d3b3f6b2349c9a32e85f5741994141d639	refs/tags/v1.0.0
d987eb2818ecd11b750962516f4914abbf73c9e5	refs/tags/v1.0.0^{}
e0c1d14af808adc5c41d285e1cf564ccb9d1e3eb	refs/tags/v1.1.0
50b52967994d63bdf526d23e3a0d7ab50b3b21cb	refs/tags/v1.1.0^{}

Empat baris tersisa — dua tag annotated, masing-masing dengan baris peeled ^{}. Dokumentasi lengkap opsi tag pada git push tersedia di git-push .

Tag kini bisa berpergian: dikirim eksplisit, ditarik otomatis, dihapus secara sadar. Pertanyaan berikutnya menyentuh isi namanya: dari mana angka 1.0, 0.1, 1.1 itu seharusnya datang, dan kapan satu angka boleh naik? Jawaban itu sudah distandarkan bernama Semantic Versioning — pokok chapter berikutnya: Semantic Versioning .