Web Artisan
Chapter 02 · Git

Alur Kerja Harian
Stage, Commit, History

Inti pekerjaan sehari-hari dengan Git adalah satu loop kecil yang berulang: pilih perubahan dengan sadar, bungkus jadi commit yang baik, lalu baca kembali jejaknya saat dibutuhkan.

Staging sadarCommit atomic~22 menit baca

Di Chapter 1 kita paham Git menyimpan snapshot lewat tiga area. Chapter ini mengubah pemahaman itu menjadi kebiasaan harian yang berputar mulus: tracking untuk memilih apa yang masuk, commit untuk membungkusnya jadi catatan yang bermakna, dan history untuk membacanya kembali. Ketiganya satu lingkaran, makin rapi kamu memilih dan menulis, makin berharga history yang bisa kamu baca berbulan-bulan kemudian.

01

Tracking Perubahan

status, add, restore, diff: memilih perubahan dengan sadar

Git memisahkan perubahan menjadi tiga kondisi, dan justru di pemisahan itulah letak kendali kamu atas apa yang masuk ke sebuah commit.

Sebuah file yang kamu sentuh hidup di salah satu dari tiga kondisi: modified (sudah diubah di working tree tapi belum ditandai), staged (sudah dipilih ke staging area, siap dibungkus jadi commit), dan committed (sudah tersimpan permanen di repository). Staging area inilah yang sering diremehkan pemula: ia bukan sekadar formalitas sebelum commit, melainkan ruang untuk menyusun commit secara sadar, memilih perubahan mana yang layak masuk bersama dan mana yang ditunda.

Tiga area Git: working tree, staging, repository Working tree file yang kamu edit Staging area (index) yang dipilih Repository (.git) history git add git commit git restore git restore --staged add memajukan ke staging, commit menyimpan ke history, restore membatalkan kembali.
Tiga area Git. git add memindahkan dari working tree ke staging; git commit menyimpan staging ke repository; git restore membatalkan.

Titik masuknya selalu git status. Perintah ini membaca ketiga area dan memberitahu kamu: file mana yang modified tapi belum staged, file mana yang sudah staged, dan file mana yang sama sekali belum dilacak (untracked). Biasakan menjalankannya sebelum dan sesudah git add, karena ia adalah kompasmu, bukan sekadar laporan.

Terminal
$ git status On branch main Changes to be committed: (use "git restore --staged <file>..." to unstage) modified: internal/product/handler.go Changes not staged for commit: (use "git add <file>..." to update what will be committed) (use "git restore <file>..." to discard changes in working directory) modified: internal/product/service.go

Untuk memindahkan perubahan ke staging, git add <path>. Untuk membatalkan, ada dua arah yang sering tertukar. git restore <file> membuang perubahan di working tree (mengembalikan file ke kondisi terakhir di index, perubahanmu hilang). Sementara git restore --staged <file> hanya meng-unstage: perubahan tetap ada di working tree, hanya dikeluarkan dari staging. Perhatikan perbedaannya: yang satu membuang isi, yang satu hanya menarik dari antrean commit.

⚠️git restore tanpa --staged itu destruktif

git restore service.go menimpa file dengan versi index dan tidak masuk reflog, jadi perubahan working tree yang belum di-commit benar-benar lenyap. Pastikan kamu memang ingin membuangnya.

Dua perintah diff menjawab dua pertanyaan berbeda. git diff menunjukkan selisih working tree vs index: perubahan yang sudah kamu buat tapi belum di-stage. git diff --staged menunjukkan index vs HEAD: persis apa yang akan tercatat bila kamu commit sekarang. Membaca keduanya sebelum commit adalah kebiasaan yang memisahkan commit rapi dari commit berantakan.

🌉Jembatan: dari review di editor ke git diff

Sama seperti kamu memindai diff di tab Source Control sebelum stage, git diff dan git diff —staged adalah versi terminal yang portabel, bisa di-pipe, dan tidak bergantung pada editor mana pun.

Mari praktik. Ubah dua file, stage satu, lalu bandingkan kedua diff sebelum commit.

Terminal
$ git add internal/product/handler.go # stage satu file saja $ git diff # sisa yang BELUM di-stage (service.go) $ git diff --staged # yang AKAN masuk commit (handler.go) $ git commit -m "Validate price is positive in product handler"

Di dunia nyata, kemampuan memilih potongan inilah yang menyelamatkan history. Bayangkan kamu sedang memperbaiki validasi harga, tapi di tengah jalan iseng merapikan nama variabel di fungsi yang sama. Dua hal itu tidak berhubungan, dan menggabungnya jadi satu commit membuat keduanya sulit dipisah nanti. git add -p menyelesaikan ini: ia menampilkan tiap hunk dan bertanya y/n, sehingga satu file berisi dua perubahan bisa dipecah jadi dua commit terpisah.

Refleks: git add .
  • Menyapu semua perubahan tanpa kamu lihat.
  • Perbaikan bug dan rename tak relevan tercampur di satu commit.
  • Rentan ikut menstage file rahasia atau setengah jadi.
Sadar: git add -p
  • Menapis per hunk, kamu memutuskan tiap potongan.
  • Tiap commit tetap atomic, satu ide per commit.
  • Diff sempat kamu baca ulang sebelum masuk staging.
02

Commit yang Baik

Atomic, pesan jelas, why over what

Commit yang baik bukan tentang menyimpan kode, melainkan menulis catatan yang masih masuk akal saat dibaca enam bulan kemudian oleh orang yang lupa konteksnya, termasuk dirimu sendiri.

Prinsip pertama adalah atomic: satu commit memuat satu perubahan logis yang utuh. Bukan “satu file”, bukan “satu hari kerja”, tapi satu ide yang bisa dijelaskan dalam satu kalimat. Commit atomic membuat git log mudah dibaca, git revert aman (membatalkan satu commit tidak ikut menghapus hal lain), dan git bisect efektif saat memburu bug. Bila kamu menggabungkan perbaikan validasi harga dengan rename variabel di satu commit, dua-duanya jadi sulit dipisah lagi nanti. Inilah kenapa git add -p di section sebelumnya penting: ia alat untuk menjaga keatomikan.

🌉Jembatan: satu issue, satu commit logis

Seperti memecah satu task besar di issue tracker jadi sub-task kecil yang jelas, satu perubahan logis sebaiknya menjadi satu commit terisolasi. Issue memberi batas; commit menjadi jejak teknis dari batas itu.

Prinsip kedua adalah pesan yang menjelaskan kenapa. Pesan commit punya dua bagian: subject (baris pertama) dan body (paragraf setelah baris kosong). Subject ditulis imperatif dan singkat, sekitar maksimal 50 karakter, seolah memberi perintah: “Add”, “Fix”, “Refactor”, bukan “Added” atau “Fixing”. Body, yang opsional, dibungkus sekitar 72 karakter per baris dan menjelaskan kenapa perubahan ini perlu, bukan mengulang apa yang sudah terbaca dari diff. Konvensi 50/72 ini bukan rewel gaya: subject pendek tampil utuh di git log --oneline, di daftar PR, dan di antarmuka hosting tanpa terpotong.

BurukBaikKenapa
updateAdd price validation to product handlerSubjek buruk tak menjelaskan apa pun saat dibaca di log.
fix bugFix negative PriceRupiah passing validation”Bug” yang mana? Subjek baik menyebut gejala spesifik.
wipRefactor product service to accept context”wip” tidak punya makna di history permanen.
⚠️Hindari pesan tanpa makna

Pesan seperti wip, update, fix bug, atau asdf membuat history jadi kabut. Saat kamu menelusuri kenapa sebuah baris berubah, pesan kosong memaksamu membaca seluruh diff dari nol.

Berikut anatomi pesan commit yang lengkap: subject imperatif singkat, baris kosong, lalu body yang menjawab “kenapa”.

Pesan commit
Reject negative price at product creation PriceRupiah disimpan sebagai int64 dalam rupiah penuh, tapi handler lama menerima nilai negatif tanpa keluhan, lalu lolos sampai ke database. Validasi di tepi mencegah data harga rusak masuk ke sistem diskon yang mengandalkan nilai non-negatif.

Prinsip ketiga: pecah perubahan besar jadi beberapa commit logis. Bila satu sesi kerja menyentuh validasi, lalu rename, lalu perbaikan test, stage dan commit terpisah dengan bantuan git add -p agar tiap commit tetap atomic.

Terminal
$ git add -p internal/product/service.go # pilih hunk validasi saja $ git commit -m "Reject negative price at product creation" $ git add -p internal/product/service.go # sekarang hunk rename $ git commit -m "Rename priceCents to priceRupiah for clarity"
💡Subject imperatif, why di body

Tulis subject seolah melengkapi kalimat “Commit ini akan …”: Add, Fix, Refactor. Simpan alasan dan trade-off di body, karena diff sudah menjawab “apa”, yang hilang justru “kenapa”.

Format pesan terstruktur ini punya kelanjutan yang kuat. Di Chapter 6 kita lihat bagaimana konvensi type(scope): description (Conventional Commits) membuat pesan bisa dibaca mesin untuk menghasilkan changelog dan menentukan versi rilis otomatis. Kebiasaan menulis subject imperatif yang jelas sekarang adalah modal untuk otomasi itu nanti.

03

Membaca History

log, show, diff tanpa rasa takut

History bukan museum yang hanya dipajang, melainkan alat investigasi: ia menjawab kenapa sebuah baris ada, kapan sebuah bug masuk, dan apa yang berubah di antara dua rilis.

Pintu utamanya git log. Apa adanya ia menampilkan tiap commit beserta hash, author, date, dan pesan, dari yang terbaru ke terlama. Tapi yang membuatnya berguna adalah flag-flagnya. --oneline memampatkan tiap commit jadi satu baris. --graph menggambar struktur cabang dengan garis ASCII. --all menyertakan semua branch, bukan hanya yang sedang aktif. Dikombinasikan, ketiganya memberi peta repositori yang cepat dibaca.

Terminal
$ git log --oneline --graph --all * 8f3a1c2 (HEAD -> main) Reject negative price at product creation * a1b9d04 Add price validation to product handler | * 4c7e8f1 (feat/discount) Add discount engine skeleton |/ * 2d5a6b3 Initialize skincare-backend module layout

Peta cabang dari satu perintah. Garis menunjukkan feat/discount bercabang dari commit yang sama dengan main.

Secara model, history adalah rantai commit yang tiap simpulnya menunjuk ke induknya. Pada satu branch lurus, rantai itu terlihat seperti ini.

gitGraph
  commit id: "init module"
  commit id: "add handler"
  commit id: "validate price"
  commit id: "reject negative"

Rantai commit linear. Tiap commit menyimpan snapshot penuh dan menunjuk ke induknya, sehingga history bisa ditelusuri mundur.

Beberapa “lensa” history paling sering kamu pakai di kerja nyata, masing-masing menjawab satu pertanyaan investigasi yang berbeda.

git show <hash>

Lihat satu commit utuh: metadata plus diff lengkapnya. Pertanyaan: “apa persisnya yang commit ini ubah?“

git diff a..b

Selisih dari commit a ke b. Pertanyaan: “apa yang berubah sejak tag rilis terakhir?“

git log -p — path/file

Riwayat plus diff satu file. Pertanyaan: “bagaimana file ini berevolusi?“

git log —follow — file

Tetap menelusuri meski file pernah di-rename. Pertanyaan: “siapa dan kapan menyentuh ini, lintas rename?”

Terminal
$ git show 8f3a1c2 # metadata + diff satu commit $ git diff a1b9d04..8f3a1c2 # selisih antara dua commit $ git log -p -- internal/product/service.go # riwayat + diff satu file $ git log --follow -- internal/product/price.go # ikut menembus rename file

Sering yang kamu butuhkan bukan seluruh history, melainkan siapa yang menyentuh satu file. git log -- path/file menyaring commit yang mengubah file tersebut, dan --follow membuat penelusuran tetap utuh meski file pernah di-rename. Tambahkan -p untuk melihat diff tiap perubahannya, sehingga evolusi sebuah file terbaca seperti cerita.

🌉Jembatan: dari browser history ke timeline proyek

Seperti history browser yang membiarkanmu kembali ke halaman sebelumnya, git log adalah timeline proyek: tiap commit adalah titik yang bisa kamu kunjungi, bandingkan, dan pahami konteksnya.

💡Alias peta cepat

git log —oneline —graph —all adalah perintah yang paling sering kamu butuhkan untuk orientasi. Jadikan alias (mis. git lg) lewat git config agar peta cabang selalu satu ketikan jauhnya.

📝History adalah catatan keputusan

Yang berharga dari history bukan kodenya saja (itu ada di file sekarang), melainkan urutan keputusan: kenapa pendekatan A dipilih lalu diganti B. Itulah sebabnya pesan commit yang menjelaskan “kenapa” membuat history jauh lebih bernilai.

04

Ringkasan

Loop harian yang menjaga history tetap berharga

Tracking, commit, dan history adalah satu lingkaran: kualitas dua yang pertama menentukan nilai yang ketiga.

Kamu kini punya loop harian yang utuh. Staging memberi kendali memilih perubahan dengan sadar, lebih baik git add -p ketimbang refleks git add .. Commit atomic dengan subject imperatif dan body yang menjelaskan “kenapa” membuat tiap titik history bermakna. Dan git log, git show, serta git diff mengubah history dari arsip pasif menjadi alat investigasi. Di Chapter 3 kita keluar dari satu garis lurus ini: bekerja paralel lewat branch, lalu menyatukannya dengan merge dan menyelesaikan konflik.

Yang Wajib Menempel

  • Tiga kondisi file, modified, staged, committed, dan staging adalah ruang menyusun commit.
  • git add -p memecah perubahan tak berkaitan; git restore tanpa —staged itu destruktif.
  • Commit atomic: satu ide per commit, subject imperatif maksimal 50 karakter, body menjawab “kenapa”.
  • git log —oneline —graph —all memberi peta; show/diff/log —follow menjawab pertanyaan investigasi spesifik.
  • Kualitas commit hari ini adalah nilai history yang kamu baca berbulan-bulan kemudian.