Seluruh section ini membangun otomasi yang berjalan di mesin kita — hooks di laptop, skrip di folder proyek. Pipeline CI/CD memindahkan otomasi itu ke server: setiap push memicu serangkaian pekerjaan, hasilnya menentukan boleh-tidaknya sebuah perubahan menyatu ke branch utama. Dan di setiap tahap pipeline itu, mesin yang bekerja tetap Git — menyalin kode, membaca tag, mengekstraksi versi, menimbang commit. Chapter penutup ini memetakan peran-peran itu dengan bukti nyata di sandbox, dari trigger hingga contoh konfigurasi pipeline utuh.

Trigger: Push dan Tag Sebagai Peristiwa #

Pipeline hidup dari peristiwa, dan dua peristiwa Git paling penting adalah push dan pembuatan tag. Platform hosting menangkapnya lewat webhook: konfigurasi di server hosting yang memberi tahu server CI — lewat HTTP — setiap kali ada push, lengkap dengan nama repository dan nama branch. Tidak ada daemon yang memantau; Git di sisi server menjalankan hook post-receive seperti yang kita pasang di Server-Side Hooks , dan platform meneruskannya menjadi notifikasi. Tag berperan sebagai trigger rilis: pipeline untuk push menjalankan tes, pipeline untuk tag v* membangun dan menerbitkan artefak.

Checkout: Clone yang Dipangkas #

Pekerjaan pertama setiap pipeline adalah menyalin kode pada commit yang tepat — dan di sinilah pemeriksaan penghematan pertama. Runner CI tidak butuh sepuluh tahun riwayat untuk menjalankan tes pada satu commit:

bash
mkdir latihan-cicd && cd latihan-cicd
git init -b main
git config user.name "Budi Santoso"
git config user.email "[email protected]"

Repository ini nanti kita isi tiga commit dan dua tag — pembuatannya menyusul bersama versinya. Shallow clone memangkas salinan menjadi satu commit:

bash
cd ..
git clone --depth 1 "file://$PWD/latihan-cicd" runner
git -C runner log --oneline
git -C runner rev-parse --is-shallow-repository

Output yang Dihasilkan (dua perintah terakhir):

text
f5307df chore: siapkan build
true

--depth 1 membawa tepat satu commit — penghematan yang diukur dan dijelaskan tuntas di Shallow Clone . Untuk monorepo raksasa, pemangkasan sumbu kedua adalah sparse-checkout — menyalin riwayat penuh tetapi hanya menuliskan sebagian direktori ke working directory, sehingga pipeline frontend tidak ikut mengunduh kode backend. Konfigurasi pipeline seperti GitHub Actions bahkan memakai shallow clone sebagai bawaan aksinya.

Versioning: Tag Menjadi Versi Build #

Setiap artefak build butuh nama versi, dan sumber kebenarannya adalah riwayat Git. Isi dulu repository tadi — tiga commit, tag pada dua di antaranya:

bash
cd latihan-cicd
printf 'situs v1\n' > situs.md && git add situs.md
GIT_AUTHOR_DATE="2026-11-13T09:00:00+07:00" GIT_COMMITTER_DATE="2026-11-13T09:00:00+07:00" \
  git commit -m "feat: halaman situs"
git tag -a v1.0.0 -m "Rilis pertama"
printf 'pencarian\n' > cari.md && git add cari.md
GIT_AUTHOR_DATE="2026-11-13T09:10:00+07:00" GIT_COMMITTER_DATE="2026-11-13T09:10:00+07:00" \
  git commit -m "feat: tambah pencarian"
git tag -a v1.1.0 -m "Rilis kedua"
printf 'perbaikan\n' > fix.md && git add fix.md
GIT_AUTHOR_DATE="2026-11-13T09:20:00+07:00" GIT_COMMITTER_DATE="2026-11-13T09:20:00+07:00" \
  git commit -m "fix: perbaiki tautan rusak"
printf 'artefak\n' > build.txt && git add build.txt
GIT_AUTHOR_DATE="2026-11-13T09:25:00+07:00" GIT_COMMITTER_DATE="2026-11-13T09:25:00+07:00" \
  git commit -m "chore: siapkan build"
git describe --tags

Output yang Dihasilkan (perintah terakhir):

text
v1.1.0-2-gf5307df

git describe membaca keluarannya: v1.1.0 adalah tag terdekat di belakang commit saat ini, 2 jumlah commit sejak tag itu, dan gf5307df hash pendek commit saat ini — deskripsi yang unik per commit dan selalu naik monoton. Ketika HEAD tepat berada di tag, keluarannya bersih: git describe --tags v1.1.0 menghasilkan v1.1.0. Dan bila repository belum bertag sama sekali, git describe --tags gagal dengan fatal: No names found, cannot describe anything. — alasan pipeline selalu menambahkan --always, yang membuat Git jatuh ke hash pendek sebagai nama versi terakhir (diuji nyata: repository tanpa tag menghasilkan a3e8879). Pola pembungkusannya:

bash
printf 'versi=%s\nsha=%s\n' "$(git describe --tags --always)" "$(git rev-parse --short HEAD)" \
  > artefak-versi.txt
cat artefak-versi.txt

Output yang Dihasilkan (perintah terakhir):

text
versi=v1.1.0-2-gf5307df
sha=f5307df

Artefak kini membawa versi dan SHA-nya — jejak lengkap dari biner kembali ke commit.

Jebakan Versioning di Shallow Clone #

Kedua teknik di atas bertabrakan dengan cara yang nyata. git describe butuh menelusuri riwayat dari commit ke tag; shallow clone memotong persis tautan itu:

bash
cd ../runner
git fetch --depth 1 origin +refs/tags/v1.1.0:refs/tags/v1.1.0 >/dev/null
git describe --tags

Output yang Dihasilkan (perintah terakhir):

text
fatal: No tags can describe 'f5307df040caa65cefbbdef30ef7b8985306ba7a'.
Try --always, or create some tags.

Tag v1.1.0 sudah terunduh, tapi commit yang ditunjuknya tidak berada dalam riwayat yang dipangkas — describe menyerah. Obatnya satu perintah:

bash
git fetch --unshallow origin >/dev/null
git describe --tags

Output yang Dihasilkan (perintah terakhir):

text
v1.1.0-2-gf5307df

Inilah dilema desain pipeline yang paling sering menjengkelkan: --depth 1 menghemat menit unduhan, git describe menuntut riwayat. Pipeline yang memakai tag sebagai versi harus mengorbankan salah satunya — atau memanggil git describe dengan --always dan menerima versi berbentuk hash.

Changelog dan Proteksi: Dua Otomasi Turunan #

Dua peran Git lainnya menyusul tanpa perintah baru. Pertama, changelog otomatis: pesan commit Conventional Commits — yang hook commit-msg kita validasi di Commit-Msg Hook — bisa diurai mesin; alat seperti commitlint atau semantic-release memilah commit feat dan fix sejak tag sebelumnya menjadi daftar perubahan, bahkan menentukan kenaikan versi semantik. Manual menyusunnya sudah dibahas di Changelog ; otomasinya mengubah sumbernya dari git log mentah menjadi riwayat yang rapi karena ditegakkan hook dan CI. Kedua, status checks: keberhasilan pipeline dilaporkan balik ke platform dan menjadi syarat merge di branch terlindungi — mekanisme proteksi penuhnya di Protected Branches . Pull request dengan tes merah menolak digabung, menutup lingkaran dari trigger hingga gerbang.

Contoh Pipeline Utuh #

Konfigurasi berikut adalah pipeline nyata bentuk GitHub Actions — teks konfigurasi, bukan keluaran — yang merangkai seluruh peran di atas:

yaml
name: ci
on:
  push:
    branches: [main]
  pull_request:

jobs:
  uji:
    runs-on: ubuntu-latest
    steps:
      - name: Ambil kode (shallow bawaan aksi checkout)
        uses: actions/checkout@v4
      - name: Pasang dependensi
        run: npm ci
      - name: Jalankan tes
        run: npm test
      - name: Baca versi dari tag
        run: |
          versi=$(git describe --tags --always || echo tanpa-tag)
          echo "versi=$versi" >> "$GITHUB_OUTPUT"
        id: versi

Kuncinya di dua tempat: on.push dan on.pull_request adalah trigger yang dibicarakan di awal; actions/checkout@v4 secara bawaan melakukan shallow clone fetch-depth: 1 — persis --depth 1 kita — sehingga langkah “Baca versi” memakai --always untuk bertahan di riwayat yang dipangkas. Pipeline yang butuh describe penuh menambahkan with: fetch-depth: 0. Ringkasan alurnya:

Ringkasan peran Git di pipeline: push dan tag adalah peristiwanya, checkout adalah salinannya, tag adalah sumber versinya, SHA adalah identitas artefaknya, dan status check adalah suaranya. Panduan lengkap layanan CI-nya ada di dokumentasi GitHub Actions .

Hooks, alias, skrip shell, dan pipeline kini lengkap membentuk lapisan otomasi di sekeliling Git — semua berdiri di atas perintah yang kita jalankan manual sepanjang course ini. Pertanyaan berikutnya bukan lagi “apa yang bisa Git jalankan”, melainkan “bagaimana Git bekerja di dalam”: objek, hash, refs, packfile. Membuka isi perutnya menjawab pertanyaan-pertanyaan yang selama ini kita terima begitu saja — mengapa hash begitu pendek bisa unik, mengapa repository tidak membengkak — dan itulah pembuka section berikutnya: Internals dan Performa.