[{"content":"Git itu melacak snapshot dari project kamu, bukan sekadar perbedaan baris kode (diff). Setiap commit adalah gambaran utuh dari seluruh project kamu pada momen tersebut. Memahami konsep ini bakal mengubah cara kamu berpikir tentang branching, merging, dan history.\nCheatsheet ini didesain buat kerjaan development sehari-hari — tipe panduan yang bakal benar-benar kamu bookmark dan buka lagi terus-menerus.\nKonsep Utama Sebelum mulai menjalankan perintah-perintah Git, kamu harus paham dulu tiga area utama di Git:\nWorking Directory → Staging Area (Index) → Repository (.git) ↑ ↑ ↑ File kamu Apa saja yang masuk Riwayat commit di dalam disk ke commit berikutnya (snapshot permanen) Working Directory adalah tempat kamu mengedit file. Ini simpelnya adalah folder project kamu di komputer.\nStaging Area (sering disebut Index) adalah jembatan antara working directory dan repository. Di sini kamu memilih secara spesifik file mana saja yang mau dimasukkan ke commit berikutnya. Ini fitur andalan Git — kamu bisa komit sebagian perubahan saja tanpa harus semuanya langsung dimasukkan.\nRepository adalah folder .git itu sendiri. Di sinilah semua snapshot commit, branch, tag, dan konfigurasi disimpan.\nApa itu Commit? Commit adalah snapshot dari seluruh project beserta metadata pendukungnya:\ncommit 3a1f2b9 ├── tree (snapshot dari semua file) ├── parent (commit sebelumnya) ├── author: Sofyan Waldy \u0026lt;sofyan@example.com\u0026gt; ├── date: 2026-06-17 └── message: \u0026#34;Add user authentication\u0026#34; Setiap commit punya hash SHA-1 unik (contohnya 3a1f2b9c...). Hash ini dihitung dari isi kontennya langsung, jadi kalau isinya sama persis, hash yang dihasilkan juga bakal selalu sama.\nApa itu Branch? Branch di Git itu cuma pointer (penunjuk) ke sebuah commit. Sesimpel itu. Bikin branch di Git itu instan banget karena Git cuma bikin file berukuran 41-byte (berisi hash + baris baru).\nmain → commit C feature → commit C (dua-duanya menunjuk ke commit yang sama sesaat setelah branching) Apa itu HEAD? HEAD adalah pointer yang menunjuk ke branch aktif saat ini (yang mana branch tersebut menunjuk ke sebuah commit). Pas kamu pindah branch, HEAD bakal otomatis ikut pindah ke branch tersebut.\nHEAD → main → commit C Kalau kamu checkout ke commit tertentu secara spesifik (bukan ke branch), kamu bakal masuk ke kondisi detached HEAD — artinya kamu sedang tidak berada di branch mana pun.\nKonfigurasi Konfigurasi Git punya tiga level tingkatan:\nLevel Flag File Jangkauan (Scope) System --system /etc/gitconfig Semua user di komputer ini Global --global ~/.gitconfig Akun user kamu saja Local --local .git/config Repositori aktif ini saja Local bakal menimpa global, dan global bakal menimpa system.\nPengaturan Dasar # Identitas (wajib — setiap commit bakal pakai info ini) git config --global user.name \u0026#34;Sofyan Waldy\u0026#34; git config --global user.email \u0026#34;sofyan@example.com\u0026#34; # Nama branch default (biar ga pakai nama jadul \u0026#39;master\u0026#39;) git config --global init.defaultBranch main # Editor default git config --global core.editor \u0026#34;nvim\u0026#34; # Penanganan baris baru (penting kalau kerja tim beda OS) git config --global core.autocrlf input # untuk macOS/Linux git config --global core.autocrlf true # untuk Windows # Aktifkan warna di output terminal git config --global color.ui auto # Atur default pull ke rebase (riwayat komit jadi lebih rapi dibanding merge) git config --global pull.rebase true # Default push hanya untuk branch aktif saat ini git config --global push.default current # Otomatis setup remote tracking saat pertama kali push git config --global push.autoSetupRemote true Alias yang Bermanfaat # Status versi singkat git config --global alias.st \u0026#34;status -sb\u0026#34; # Log indah dengan grafik satu baris git config --global alias.lg \u0026#34;log --oneline --graph --all --decorate\u0026#34; # Amend commit terakhir tanpa ubah pesannya git config --global alias.amend \u0026#34;commit --amend --no-edit\u0026#34; # Batalkan staging untuk semua file (unstage) git config --global alias.unstage \u0026#34;reset HEAD --\u0026#34; # Detail commit terakhir git config --global alias.last \u0026#34;log -1 HEAD --stat\u0026#34; # Tampilkan semua alias yang sudah dibuat git config --global alias.aliases \u0026#34;config --get-regexp ^alias\u0026#34; # Lihat perbedaan file yang sudah di-stage git config --global alias.staged \u0026#34;diff --cached\u0026#34; # Hapus branch lokal yang sudah di-merge (kecuali main/master dan branch aktif) git config --global alias.cleanup \u0026#34;!git branch --merged | grep -v \u0026#39;\\\\*\\\\|main\\\\|master\u0026#39; | xargs -n 1 git branch -d\u0026#34; Melihat Konfigurasi # Tampilkan semua settingan beserta asal filenya git config --list --show-origin # Cek settingan spesifik git config user.email # Edit konfigurasi global langsung di editor teks git config --global --edit Workflow Dasar Memulai Project # Bikin repositori baru git init project-ku cd project-ku # Clone repositori yang sudah ada git clone https://github.com/user/repo.git # Clone ke dalam folder spesifik git clone https://github.com/user/repo.git folder-ku # Clone commit terakhir saja (cepat untuk repo berukuran besar) git clone --depth 1 https://github.com/user/repo.git # Clone branch spesifik git clone -b develop https://github.com/user/repo.git Memasukkan File ke Staging Area (Stage) # Masukkan file spesifik ke stage git add README.md # Masukkan beberapa file sekaligus git add src/index.js src/utils.js # Masukkan semua perubahan di folder aktif saat ini (rekursif) git add . # Masukkan seluruh perubahan di satu repositori penuh git add -A # Masukkan hanya file yang sudah dilacak (abaikan file baru yang belum dilacak) git add -u # Masukkan potongan baris kode secara interaktif git add -p Staging Interaktif dengan git add -p Ini salah satu fitur Git paling keren. Git bakal nampilin potongan perubahan baris kode kamu dan nanya apa yang mau kamu lakukan:\n@@ -10,6 +10,8 @@ function processUser(user) { + validateEmail(user.email); + sanitizeInput(user.name); const result = saveUser(user); Stage this hunk [y,n,q,a,d,s,e,?]? Tombol Aksi y Masukkan potongan ini ke stage n Lewati potongan ini q Keluar (jangan masukkan sisa potongan lainnya) a Masukkan potongan ini dan semua sisa potongan lainnya s Pecah potongan kode jadi lebih kecil lagi e Edit potongan kode ini secara manual Ini berguna banget biar kamu bisa bikin satu commit yang fokus dan logis, meskipun kamu lagi ngedit banyak hal yang berbeda di dalam satu file.\nMelakukan Commit # Commit perubahan yang ada di stage dengan pesan singkat git commit -m \u0026#34;Add email validation to user signup\u0026#34; # Commit dengan pesan beberapa baris git commit -m \u0026#34;Add email validation\u0026#34; -m \u0026#34;Validates format and checks for disposable providers\u0026#34; # Otomatis stage file yang sudah dilacak sekaligus commit dalam satu langkah git commit -am \u0026#34;Fix typo in error message\u0026#34; # Buka editor buat nulis pesan commit yang lebih detail git commit # Commit dengan nama author spesifik git commit --author=\u0026#34;Partner \u0026lt;partner@example.com\u0026gt;\u0026#34; -m \u0026#34;Pair programming session\u0026#34; # Bikin commit kosong (berguna untuk memicu CI/CD trigger) git commit --allow-empty -m \u0026#34;Trigger deployment pipeline\u0026#34; Menulis Pesan Commit yang Baik Add OAuth2 authentication for API endpoints - Implement token-based auth using JWT - Add refresh token rotation for security - Include rate limiting per API key - Update API documentation with auth headers Closes #142 Aturannya:\nBaris pertama: bentuk perintah (imperative), ≤50 karakter (seperti subjek email) Baris kosong sebagai pemisah antara subjek dan isi deskripsi Isi deskripsi: jelaskan apa dan kenapa (bukan bagaimana caranya — karena codenya sendiri sudah menjelaskan bagaimana caranya) Memeriksa Status # Status lengkap git status # Status versi singkat (jauh lebih gampang dibaca) git status -sb Arti output status versi singkat:\n## main...origin/main [ahead 2] M src/utils.js # Diedit tapi belum di-stage M src/index.js # Diedit dan sudah di-stage A src/newfile.js # File baru, sudah di-stage ?? docs/notes.txt # Belum dilacak (untracked) MM src/config.js # Sudah di-stage, lalu diedit lagi Dua kolom di depan: kolom kiri = staging area, kolom kanan = working directory.\nBranching (Percabangan) Branch di Git itu sangat ringan. Gunakan sesering mungkin. Setiap fitur baru, perbaikan bug, atau eksperimen harus punya branch-nya sendiri.\nMembuat Branch # Bikin branch baru (tapi posisi kamu tetap di branch aktif) git branch feature/user-auth # Bikin branch baru dan langsung pindah ke sana git switch -c feature/user-auth # Sintaks lama (masih bisa dipakai) git checkout -b feature/user-auth # Bikin branch dari commit hash tertentu git branch hotfix/login-crash abc1234 # Bikin branch dari tag tertentu git branch release/v2.1 v2.0.0 # Bikin branch lokal yang melacak branch remote git switch -c feature/api origin/feature/api Berpindah Branch # Pindah ke branch lain git switch main # Pindah balik ke branch sebelumnya (seperti cd -) git switch - # Sintaks lama git checkout main Kenapa pakai git switch dibanding git checkout? Perintah checkout itu terlalu banyak fungsinya — bisa pindah branch, restore file, sampai detach HEAD. Makanya di Git versi 2.23 dikenalkan switch (khusus urusan branch) dan restore (khusus urusan file) agar lebih teratur.\nMelihat Daftar Branch # Daftar branch lokal (* menunjukkan branch aktif) git branch # Daftar branch remote git branch -r # Daftar semua branch (lokal + remote) git branch -a # Daftar branch beserta info commit terakhirnya git branch -v # Daftar branch yang sudah di-merge ke branch aktif saat ini git branch --merged # Daftar branch yang BELUM di-merge git branch --no-merged # Daftar branch yang mengandung commit hash tertentu git branch --contains abc1234 Menghapus Branch # Hapus branch yang sudah di-merge (aman) git branch -d feature/user-auth # Hapus paksa branch yang belum di-merge (berpotensi kehilangan data) git branch -D experiment/crazy-idea # Hapus branch di server remote git push origin --delete feature/user-auth # Cara alternatif untuk menghapus branch remote git push origin :feature/user-auth Mengubah Nama Branch # Ubah nama branch aktif saat ini git branch -m nama-baru # Ubah nama branch lokal lain git branch -m nama-lama nama-baru # Ubah nama branch dan sinkronkan ke remote git branch -m nama-lama nama-baru git push origin --delete nama-lama git push origin nama-baru git push origin -u nama-baru Merging (Penggabungan) Merging adalah cara menggabungkan pekerjaan dari dua branch. Git bakal otomatis menentukan strategi merge yang pas.\nFast-Forward Merge Kalau branch target belum punya commit baru semenjak kamu bikin branch fitur, Git tinggal memajukan pointer branch target ke depan. Tidak ada commit merge tambahan yang dibuat.\nSebelum: main: A --- B \\ feature: C --- D Setelah menjalankan git merge feature (dari branch main): main: A --- B --- C --- D git switch main git merge feature/user-auth # Output: \u0026#34;Fast-forward\u0026#34; Three-Way Merge Kalau kedua branch sama-sama punya commit baru setelah terpisah, Git bakal bikin satu commit merge baru yang punya dua parent.\nSebelum: main: A --- B --- E \\ feature: C --- D Setelah menjalankan git merge feature (dari branch main): main: A --- B --- E --- M (commit merge baru) \\ / feature: C --- D git switch main git merge feature/user-auth # Output: \u0026#34;Merge made by the \u0026#39;ort\u0026#39; strategy.\u0026#34; Opsi Merge # Merge dengan pesan commit custom git merge feature/user-auth -m \u0026#34;Merge user authentication feature\u0026#34; # Paksa bikin commit merge meskipun sebenarnya bisa fast-forward # (bagus biar riwayat branch fitur tetap kelihatan terpisah) git merge --no-ff feature/user-auth # Merge tapi jangan langsung di-commit (biar bisa kita review dulu hasilnya) git merge --no-commit feature/user-auth # Batalkan proses merge yang sedang berjalan (kalau ada konflik) git merge --abort # Cek apakah branch bisa di-merge dengan aman tanpa konflik sebelum melakukan merge asli git merge --no-commit --no-ff feature/user-auth git merge --abort # batalkan merge uji coba tadi Menyelesaikan Konflik Merge (Merge Conflicts) Saat Git tidak bisa menggabungkan kode otomatis, Git bakal menandai konflik di dalam file:\n\u0026lt;\u0026lt;\u0026lt;\u0026lt;\u0026lt;\u0026lt;\u0026lt; HEAD const API_URL = \u0026#34;https://api.production.com\u0026#34;; ======= const API_URL = process.env.API_URL || \u0026#34;https://api.staging.com\u0026#34;; \u0026gt;\u0026gt;\u0026gt;\u0026gt;\u0026gt;\u0026gt;\u0026gt; feature/config-env \u0026lt;\u0026lt;\u0026lt;\u0026lt;\u0026lt;\u0026lt;\u0026lt; HEAD: versi dari branch kamu saat ini =======: batas pemisah \u0026gt;\u0026gt;\u0026gt;\u0026gt;\u0026gt;\u0026gt;\u0026gt; feature/config-env: versi dari branch yang mau kamu masukkan Langkah penyelesaian:\n# 1. Cek file mana saja yang konflik git status # 2. Buka file yang konflik dan edit manual # Hapus tanda pembatas konflik dan rapikan kodenya # 3. Setelah beres, masukkan file ke staging area git add src/config.js # 4. Selesaikan proses merge git commit # Git bakal otomatis generates pesan commit merge Cara cepat: pilih salah satu versi seutuhnya:\ngit checkout --ours src/config.js # pakai versi branch aktif kita git checkout --theirs src/config.js # pakai versi branch yang mau dimasukkan Strategi Merge # Merge tapi kalau ada konflik, otomatis pakai perubahan punya kita git merge -X ours feature/user-auth # Merge tapi kalau ada konflik, otomatis pakai perubahan dari branch sebelah git merge -X theirs feature/user-auth # Strategi \u0026#34;Ours\u0026#34; — anggap merge selesai tapi buang semua perubahan dari branch sebelah # (berbeda dari -X ours — ini mengabaikan SEMUA perubahan, bukan cuma yang konflik) git merge -s ours feature/deprecated-api Rebasing Rebasing itu memindahkan dasar (base) branch kamu ke commit paling ujung dari branch lain, membuat riwayat commit jadi lurus (linear). Ini bakal menulis ulang hash commit.\nRebase Standar Sebelum: main: A --- B --- E \\ feature: C --- D Setelah menjalankan git rebase main (dari branch feature): main: A --- B --- E \\ feature: C\u0026#39; --- D\u0026#39; (commit baru dengan perubahan yang sama) # Dari branch fitur kamu git switch feature/user-auth git rebase main C\u0026rsquo; dan D\u0026rsquo; adalah commit baru — isinya sama tapi hash commit-nya berubah karena parent-nya sudah berganti. Commit C dan D lama bakal ditinggalkan (dan otomatis dibersihkan oleh sistem berkala).\nInteractive Rebase (Rebase Interaktif) Rebase interaktif membolehkan kamu edit, gabungkan (squash), susun ulang, atau hapus commit. Ini cara terbaik merapikan history commit yang berantakan sebelum di-merge ke main.\n# Lakukan rebase interaktif untuk 4 commit terakhir git rebase -i HEAD~4 # Lakukan rebase interaktif dari titik awal pisah dengan branch main git rebase -i main Git bakal membuka editor dengan teks seperti ini:\npick a1b2c3d Add user model pick e4f5g6h Add user controller pick i7j8k9l Fix typo in user model pick m0n1o2p Add user validation # Perintah: # p, pick = gunakan commit ini # r, reword = gunakan commit ini, tapi edit pesan commit-nya # e, edit = gunakan commit ini, tapi berhenti sejenak untuk amend # s, squash = gabungkan commit ini ke commit di atasnya # f, fixup = mirip \u0026#34;squash\u0026#34;, tapi buang pesan commit ini (pakai pesan commit atasnya) # d, drop = hapus commit ini # x, exec = jalankan perintah shell Skenario Rebase Interaktif yang Sering Dipakai Menggabungkan commit \u0026ldquo;fix typo\u0026rdquo; ke commit aslinya:\npick a1b2c3d Add user model fixup i7j8k9l Fix typo in user model ← diubah dari pick ke fixup pick e4f5g6h Add user controller pick m0n1o2p Add user validation Mengubah pesan commit lama:\nreword a1b2c3d Add user model ← diubah dari pick ke reword pick e4f5g6h Add user controller pick m0n1o2p Add user validation Menyusun ulang urutan commit:\npick m0n1o2p Add user validation ← dipindahkan ke atas pick a1b2c3d Add user model pick e4f5g6h Add user controller Menghapus commit seutuhnya:\npick a1b2c3d Add user model drop e4f5g6h Add user controller ← commit ini bakal hilang pick m0n1o2p Add user validation Menyelesaikan Konflik saat Rebase # Kalau ada konflik pas rebase, beresin dulu kodenya lalu: git add src/conflicted-file.js git rebase --continue # Lewati commit ini git rebase --skip # Batalkan proses rebase dan balikkan ke kondisi sebelum mulai rebase git rebase --abort Rebase vs Merge Aspek Merge Rebase Riwayat (History) Menjaga riwayat asli apa adanya dengan commit merge Bikin riwayat lurus dan bersih Hash Commit Tetap sama Ditulis ulang (bikin hash baru) Konflik Cukup selesaikan sekali Bisa jadi harus menyelesaikan per commit Branch Bersama Aman Bahaya — jangan pernah rebase branch yang dipakai bersama Kegunaan Integrasi akhir Merapikan riwayat sebelum digabung Aturan Emas: Jangan pernah melakukan rebase pada commit yang sudah kamu push ke repositori bersama. Kamu bakal merusak riwayat kerjaan tim lain yang mengambil update dari branch tersebut.\n# Aman: rebase branch fitur lokal kamu ke main git switch feature/my-work git rebase main # BAHAYA: rebase branch main setelah orang lain mengambil update dari sana git switch main git rebase feature/something # JANGAN LAKUKAN INI Workflow Autosquash Cara super rapi untuk memperbaiki commit yang sudah lalu:\n# Kamu sadar commit abc1234 ada bug. Bikin commit perbaikan khusus (fixup): git commit --fixup=abc1234 # Nanti, gabungkan semua commit perbaikan otomatis ke commit targetnya: git rebase -i --autosquash main # Git bakal otomatis menandai perintah commit perbaikan dengan status \u0026#34;fixup\u0026#34; Remote Repository (Repositori Server) Mengelola Remote # Tampilkan daftar remote git remote -v # Tambah remote baru git remote add origin https://github.com/user/repo.git # Tambah remote sekunder (misal repositori utama/hulu) git remote add upstream https://github.com/original/repo.git # Ubah nama panggilan remote git remote rename origin github # Hapus remote git remote remove upstream # Ubah URL remote (misal dari HTTPS ke SSH) git remote set-url origin git@github.com:user/repo.git # Tampilkan info detail tentang remote tertentu git remote show origin Fetch, Pull, Push Fetch mendownload perubahan dari server tapi tidak langsung menggabungkannya ke file aktif kamu:\n# Fetch dari remote default (origin) git fetch # Fetch dari remote spesifik git fetch upstream # Fetch branch spesifik saja git fetch origin main # Fetch dari semua remote git fetch --all # Fetch sekaligus bersihkan branch remote yang sudah dihapus di server git fetch --prune Pull itu gabungan dari fetch + merge (atau fetch + rebase kalau diatur begitu):\n# Pull branch aktif saat ini git pull # Pull dengan rebase alih-alih merge (riwayat commit lebih rapi) git pull --rebase # Pull dari branch spesifik git pull origin main # Pull sekaligus otomatis simpan sementara perubahan lokal (autostash) git pull --autostash Push mengunggah commit kamu ke server:\n# Push branch aktif saat ini git push # Push dan atur default tracking untuk pertama kali git push -u origin feature/user-auth # Push semua branch sekaligus git push --all # Push semua tag git push --tags # Push paksa (BAHAYA — menimpa riwayat di server) git push --force # Push paksa dengan verifikasi (jauh lebih aman — bakal gagal kalau server punya update baru dari orang lain) git push --force-with-lease # Push branch lokal ke nama branch remote yang berbeda git push origin branch-lokal:branch-remote Selalu biasakan pakai --force-with-lease daripada --force. Opsi ini memastikan remote server tidak punya update baru dari orang lain sejak fetch terakhirmu. Jadi kamu tidak sengaja menimpa kerjaan teman satu tim.\nMelacak Branch (Tracking Branches) # Atur tracking upstream untuk branch aktif saat ini git branch --set-upstream-to=origin/main # Lihat info relasi tracking antar branch git branch -vv # Contoh output: # feature/auth abc1234 [origin/feature/auth: ahead 2] Add JWT support # main def5678 [origin/main] Update README # * develop ghi9012 [origin/develop: behind 3] Refactor API ahead 2 berarti kamu punya 2 commit lokal yang belum di-push. behind 3 berarti server punya 3 commit baru yang belum kamu ambil (pull).\nBekerja dengan Repositori Fork # 1. Fork repositori di GitHub, lalu clone hasil fork kamu sendiri git clone https://github.com/akun-kamu/repo.git # 2. Daftarkan repositori asli sebagai remote bernama \u0026#34;upstream\u0026#34; git remote add upstream https://github.com/original/repo.git # 3. Cara menyinkronkan fork kamu agar tetap update: git fetch upstream git switch main git merge upstream/main git push origin main # 4. Bikin branch baru untuk mulai berkontribusi git switch -c feature/kontribusi-saya Stashing (Penyimpanan Sementara) Stash menyimpan perubahan kode yang belum di-commit untuk sementara waktu — mirip seperti menyimpan barang di laci meja kerja agar meja bersih dulu, nanti tinggal diambil lagi.\nPerintah Dasar Stash # Simpan perubahan sementara (hanya file yang sudah dilacak) git stash # Simpan stash disertai deskripsi pesan agar mudah diingat git stash push -m \u0026#34;WIP: login form setengah jalan\u0026#34; # Simpan stash termasuk file baru yang belum dilacak (untracked) git stash -u # Simpan semuanya, termasuk file yang diabaikan (.gitignore) git stash -a # Simpan stash untuk file spesifik saja git stash push -m \u0026#34;Simpan settingan config\u0026#34; src/config.js src/env.js # Pilih potongan mana saja yang mau disimpan ke stash secara interaktif git stash -p Mengambil Kembali Stash # Terapkan stash terakhir (tapi file stash tetap disimpan di daftar) git stash apply # Terapkan stash terakhir dan hapus dari daftar stash git stash pop # Terapkan stash nomor tertentu git stash apply stash@{2} # Terapkan dan hapus stash nomor tertentu git stash pop stash@{1} Mengelola Stash # Lihat daftar semua stash yang tersimpan git stash list # Contoh output: # stash@{0}: On feature/auth: WIP login form setengah jalan # stash@{1}: On main: Perbaikan cepat coba-coba # stash@{2}: WIP on develop: abc1234 Add API routes # Tampilkan perbedaan isi file di dalam stash git stash show git stash show -p # tampilkan detail kode yang berbeda git stash show stash@{2} -p # tampilkan detail kode stash tertentu # Hapus salah satu stash dari daftar git stash drop stash@{1} # Hapus SEMUA stash (hati-hati, ini permanen!) git stash clear # Bikin branch baru dari isi stash (sangat berguna kalau stash bentrok dengan kondisi branch aktif) git stash branch nama-branch-baru stash@{0} Kasus Nyata Penggunaan Stash Skenario: Kamu harus buru-buru pindah branch tapi ada kerjaan yang belum selesai di-commit:\ngit stash push -m \u0026#34;Belum selesai: login screen\u0026#34; git switch main # ... selesaikan kerjaan perbaikan cepat ... git switch feature/login git stash pop Skenario: Kamu tidak sengaja menulis kode di branch yang salah:\n# Kamu nulis kode di main, padahal harusnya di feature/api git stash git switch feature/api git stash pop Log dan Riwayat History Log Dasar # Log standar git log # Log format ringkas (satu baris per commit) git log --oneline # Tampilkan 5 commit terakhir saja git log -5 # Tampilkan log beserta perbedaan kodenya (diff) git log -p # Tampilkan statistik file yang berubah (baris tambah/kurang) git log --stat # Tampilkan statistik versi ringkas git log --shortstat Mempercantik Format Log # Tampilkan grafik riwayat percabangan lengkap git log --oneline --graph --all --decorate # Format log kustom git log --pretty=format:\u0026#34;%h %ad | %s%d [%an]\u0026#34; --date=short # Arti kode format penampung (placeholders): # %h = hash commit versi pendek # %H = hash commit versi lengkap # %an = nama pembuat commit (author) # %ae = email pembuat commit # %ad = tanggal commit dibuat # %s = subjek commit (baris pertama pesan) # %b = isi detail pesan commit (body) # %d = nama referensi (branch, tag) Contoh output git log --oneline --graph --all:\n* 3a1f2b9 (HEAD -\u0026gt; feature/auth) Add JWT validation * c4d5e6f Implement login endpoint | * 8f9a0b1 (main) Update README |/ * 1a2b3c4 Initial project setup Memfilter Log # Cari commit berdasarkan nama author git log --author=\u0026#34;Sofyan\u0026#34; # Cari commit dalam rentang tanggal tertentu git log --after=\u0026#34;2026-01-01\u0026#34; --before=\u0026#34;2026-06-01\u0026#34; # Cari commit yang pesannya mengandung kata tertentu git log --grep=\u0026#34;authentication\u0026#34; # Cari commit yang memodifikasi file spesifik git log -- src/auth.js # Cari commit yang menambah atau menghapus teks kode tertentu git log -S \u0026#34;API_KEY\u0026#34; # pencarian tipe pickaxe # Cari commit menggunakan regex pada isi perubahan kode git log -G \u0026#34;function\\s+auth\u0026#34; # Cari perbedaan commit di antara dua referensi git log main..feature/auth # commit di feature/auth yang ga ada di main git log main...feature/auth # commit yang ada di salah satu tapi ga keduanya # Tampilkan commit di branch A tapi lewatkan branch B git log feature/auth --not main Git Blame Melihat siapa yang terakhir kali mengubah baris kode di suatu file:\n# Blame satu file git blame src/auth.js # Blame hanya untuk baris tertentu git blame -L 10,20 src/auth.js # Abaikan perubahan spasi saja git blame -w src/auth.js # Deteksi kode yang dipindahkan atau disalin dari baris lain git blame -M src/auth.js # Deteksi kode yang disalin dari file lain git blame -C src/auth.js Contoh output:\na1b2c3d4 (Sofyan 2026-03-15 10:30:00 +0700 1) const express = require(\u0026#39;express\u0026#39;); e5f6g7h8 (Partner 2026-04-01 14:22:00 +0700 2) const jwt = require(\u0026#39;jsonwebtoken\u0026#39;); a1b2c3d4 (Sofyan 2026-03-15 10:30:00 +0700 3) const router = express.Router(); Git Show # Lihat isi detail commit tertentu (diff + metadata) git show abc1234 # Tampilkan hanya daftar nama file yang berubah di commit tersebut git show --stat abc1234 # Tampilkan isi file di commit tertentu masa lalu git show abc1234:src/auth.js # Tampilkan commit yang ditunjuk oleh sebuah tag git show v2.0.0 Membatalkan Perubahan (Undoing Things) Ini bagian yang paling sering bikin panik. Berikut panduan jelas mana yang aman dan mana yang berpotensi menghapus data.\nMemperbaiki Commit Terakhir # Ubah pesan commit terakhir git commit --amend -m \u0026#34;Pesan commit yang lebih baik\u0026#34; # Masukkan file yang kelupaan ke commit terakhir tanpa edit pesan commit git add file-ketinggalan.js git commit --amend --no-edit # Ganti nama author dari commit terakhir git commit --amend --author=\u0026#34;Nama Asli \u0026lt;email@asli.com\u0026gt;\u0026#34; Catatan: Perintah --amend itu mengganti commit terakhir dengan commit yang baru (hash berubah). Hanya gunakan ini untuk commit yang belum di-push ke remote, atau kamu terpaksa harus force-push nanti.\nMengeluarkan File dari Staging Area (Unstage) # Keluarkan file dari stage (tapi perubahan kodenya tetap aman di komputer) git restore --staged src/auth.js # Keluarkan semua file sekaligus git restore --staged . # Sintaks lama (masih bisa) git reset HEAD src/auth.js Membatalkan Perubahan di Working Directory # Batalkan perubahan di file tertentu (PERMANEN — perubahan kode bakal hilang!) git restore src/auth.js # Batalkan semua perubahan di folder aktif saat ini git restore . # Sintaks lama git checkout -- src/auth.js Git Reset Reset itu memindahkan pointer branch. Ada tiga mode reset yang menentukan nasib staging area dan working directory kamu:\nPointer Branch Staging Area Working Directory git reset --soft Pindah Gak Berubah Gak Berubah git reset --mixed Pindah Direset Gak Berubah git reset --hard Pindah Direset Direset Soft Reset Memindahkan pointer branch tapi menjaga file kamu tetap berada di stage. Sangat pas untuk membatalkan commit terakhir buat diperbaiki isinya.\n# Sebelum: # A --- B --- C (HEAD) git reset --soft HEAD~1 # Sesudah: # A --- B (HEAD) # Perubahan dari commit C tersimpan di stage, tinggal di-commit lagi nanti # Contoh kasus: menggabungkan 3 commit terakhir jadi 1 saja git reset --soft HEAD~3 git commit -m \u0026#34;Combined feature: user auth dengan validasi\u0026#34; Mixed Reset (Default) Memindahkan pointer branch dan mengeluarkan file dari stage, tapi membiarkan kodenya tetap aman di working directory.\n# Sebelum: # A --- B --- C (HEAD) git reset HEAD~1 # --mixed adalah pilihan default # Sesudah: # A --- B (HEAD) # Perubahan dari commit C tersimpan di working directory tapi statusnya belum di-stage # Contoh kasus: commit terlalu cepat, ingin menata ulang staging file per bagian git reset HEAD~1 git add src/model.js git commit -m \u0026#34;Add user model\u0026#34; git add src/controller.js git commit -m \u0026#34;Add user controller\u0026#34; Hard Reset (Menghapus Data!) Memindahkan pointer branch DAN membuang seluruh perubahan kode tanpa sisa.\n# Sebelum: # A --- B --- C (HEAD) # + ada juga perubahan yang belum di-stage di komputer git reset --hard HEAD~1 # Sesudah: # A --- B (HEAD) # Commit C hilang. Perubahan yang belum di-stage hilang. Semua file sama persis dengan commit B. # Contoh kasus: ingin membuang semua eksperimen kode yang gagal total git reset --hard HEAD~3 # Samakan persis isi repositori lokal dengan server remote aktif saat ini git reset --hard origin/main Peringatan: --hard adalah satu-satunya reset yang bisa melenyapkan perubahan kode yang belum di-commit secara permanen. Kalau sudah pernah di-commit sebelumnya, kodenya masih bisa diselamatkan lewat fitur reflog.\nGit Revert Revert membuat commit baru yang serves untuk membatalkan efek dari commit sebelumnya. Ini sangat aman untuk branch bersama karena tidak merusak riwayat masa lalu.\n# Sebelum: # A --- B --- C (HEAD) git revert C # Sesudah: # A --- B --- C --- C\u0026#39; (HEAD) # Commit C\u0026#39; berisi kode pembatalan dari semua hal yang dilakukan commit C # Revert commit tertentu berdasarkan hash git revert abc1234 # Batalkan perubahan di commit tertentu tapi jangan langsung di-commit (taruh di stage saja dulu) git revert --no-commit abc1234 # Batalkan commit merge (harus ditentukan induk/parent mana yang mau dipertahankan) git revert -m 1 hash-commit-merge # -m 1 artinya pertahankan parent pertama (biasanya branch utama tujuan merge) Perbandingan Reset vs Revert Fitur git reset git revert Riwayat (History) Menulis ulang (menghapus commit) Menjaga (menambahkan commit baru) Aman di Branch Bersama Tidak Ya Berisiko Hilang Data --hard bisa Tidak Kasus Penggunaan Berbenah kode lokal Membatalkan kode di branch tim Reflog — Jaring Pengaman Kamu Git merekam setiap kali pointer HEAD berpindah. Bahkan setelah kamu melakukan hard reset, kamu masih bisa mengembalikan commit yang hilang lewat reflog.\n# Tampilkan daftar reflog git reflog # Contoh output: # abc1234 HEAD@{0}: reset: moving to HEAD~3 # def5678 HEAD@{1}: commit: Add user validation # ghi9012 HEAD@{2}: commit: Add user controller # jkl3456 HEAD@{3}: commit: Add user model # Selamatkan kode! Pindahkan branch balik ke titik sebelum reset git reset --hard HEAD@{1} # Atau bikin branch baru dari commit yang sempat hilang tadi git branch selamatkan-kode def5678 Catatan: Riwayat reflog punya masa kedaluwarsa, biasanya setelah 90 hari (untuk commit yang bisa dijangkau) atau 30 hari (untuk commit yatim yang tidak terhubung). Jangan tunggu terlalu lama untuk menyelamatkannya.\nMengambil File Tertentu dari Riwayat Masa Lalu # Kembalikan file tertentu ke kondisinya pada commit hash spesifik git restore --source=abc1234 src/auth.js # Kembalikan file ke kondisinya pada 3 commit yang lalu git restore --source=HEAD~3 src/auth.js # Menyelamatkan file yang sempat terhapus: git log --diff-filter=D -- path/ke/file-yang-dihapus.js # cari commit mana yang menghapusnya git restore --source=abc1234^ path/ke/file-yang-dihapus.js # kembalikan file dari commit SEBELUM terhapus Cherry-pick Cherry-pick mengambil sebuah commit dari branch lain lalu menerapkannya ke branch aktif saat ini. Ini bakal membuat commit baru dengan isi perubahan yang sama tapi hash-nya berbeda.\n# Terapkan commit tertentu ke branch aktif saat ini git cherry-pick abc1234 # Terapkan commit tanpa langsung menjadikannya commit (taruh di stage saja) git cherry-pick --no-commit abc1234 # Cherry-pick beberapa commit sekaligus git cherry-pick abc1234 def5678 # Cherry-pick rentang commit (tidak termasuk commit awal, termasuk commit akhir) git cherry-pick abc1234..ghi9012 # Cherry-pick rentang commit (termasuk commit awal dan akhir) git cherry-pick abc1234^..ghi9012 Menyelesaikan Konflik saat Cherry-pick # Jika terjadi konflik: # 1. Bereskan konfliknya di dalam file # 2. Stage file tersebut git add src/fixed-file.js # 3. Lanjutkan cherry-pick git cherry-pick --continue # Atau batalkan cherry-pick seutuhnya git cherry-pick --abort Kapan Menggunakan Cherry-pick? # Menerapkan perbaikan bug (hotfix) dari main ke branch rilis stabil git switch release/v2.0 git cherry-pick hash-commit-hotfix # Mengambil satu commit fitur spesifik tanpa perlu merge seluruh isi branch fiturnya git switch main git cherry-pick hash-commit-fitur Catatan: Cherry-pick itu menduplikasi commit (isi sama, hash beda). Jika nanti kamu me-merge branch asalnya, Git biasanya cukup pintar menyinkronkannya, tapi bisa memicu kebingungan riwayat commit kalau terlalu sering dilakukan.\nTag (Penanda Versi) Tag digunakan untuk menandai titik penting dalam riwayat rilis — biasanya untuk nomor versi aplikasi.\nLightweight Tag (Tag Sederhana) Hanya pointer penunjuk biasa ke sebuah commit (seperti branch tapi posisinya tidak bisa bergerak maju):\n# Bikin tag sederhana di commit saat ini git tag v1.0.0 # Bikin tag pada commit spesifik di masa lalu git tag v0.9.0 abc1234 Annotated Tag (Tag Beranotasi - Direkomendasikan) Menyimpan metadata lengkap: nama pembuat, email, tanggal, dan pesan deskripsi tag. Tag ini disimpan sebagai objek Git utuh.\n# Bikin tag beranotasi git tag -a v2.0.0 -m \u0026#34;Rilis versi 2.0.0 — Dukungan OAuth2\u0026#34; # Bikin tag beranotasi pada commit tertentu git tag -a v1.5.0 -m \u0026#34;Perbaikan bug keamanan login\u0026#34; abc1234 Mengelola Tag # Tampilkan semua tag git tag # Tampilkan tag yang polanya cocok git tag -l \u0026#34;v2.*\u0026#34; # Tampilkan detail info sebuah tag git show v2.0.0 # Hapus tag di lokal komputer git tag -d v1.0.0 # Hapus tag di server remote git push origin --delete v1.0.0 # Push satu tag ke remote server git push origin v2.0.0 # Push semua tag sekaligus ke remote server git push origin --tags # Push tag beranotasi saja yang relevan dengan commit terunggah git push origin --follow-tags # Checkout ke suatu tag (masuk ke detached HEAD) git checkout v2.0.0 # Bikin branch baru dari sebuah tag git switch -c hotfix/v2.0.1 v2.0.0 Aturan Penomoran Versi (Semantic Versioning) v1.0.0 → MAJOR.MINOR.PATCH │ │ │ │ │ └── Perbaikan Bug (tidak merusak fitur lama / backward compatible) │ └───── Fitur Baru (tidak merusak fitur lama) └──────── Perubahan Besar (merusak fitur lama / breaking changes) Git Diff (Komparasi Perbedaan) Komparasi Kode yang Sedang Ditulis # Cek perbedaan di working directory yang belum dimasukkan ke stage git diff # Cek perbedaan yang sudah ada di stage (siap di-commit) git diff --staged git diff --cached # fungsi sama saja # Cek semua perubahan (stage + unstage) dibandingkan commit terakhir (HEAD) git diff HEAD # Cek perbedaan pada file tertentu saja git diff src/auth.js git diff --staged src/auth.js Komparasi Antar Branch dan Commit # Cek perbedaan antara dua branch git diff main..feature/auth # Hanya tampilkan daftar nama file yang berbeda saja git diff --name-only main..feature/auth # Tampilkan perbedaan disertai statistik ringkas git diff --stat main..feature/auth # Cek perbedaan di antara dua commit git diff abc1234 def5678 # Perbedaan antara commit lama dengan kondisi HEAD saat ini git diff abc1234 HEAD # Perubahan yang dibawa oleh salah satu commit spesifik git diff abc1234^..abc1234 # cara termudahnya: git show abc1234 Opsi Diff Lainnya # Abaikan perubahan spasi saja git diff -w # Abaikan perbedaan jumlah spasi kosong git diff -b # Tampilkan perbedaan per kata bukan per baris seutuhnya git diff --word-diff # Ekspor perbedaan kode menjadi file patch git diff \u0026gt; perubahan-saya.patch # Terapkan file patch tersebut ke repositori git apply perubahan-saya.patch Aturan .gitignore File .gitignore memberi tahu Git file atau folder mana saja yang tidak boleh dilacak. Aturan ditulis relatif terhadap posisi file .gitignore tersebut berada.\nSintaks Penulisan # Ini adalah komentar # Abaikan file spesifik bernama ini secrets.env # Abaikan semua file yang ekstensinya ini *.log *.tmp # Abaikan satu folder utuh (wajib diakhiri garis miring) node_modules/ dist/ build/ # Abaikan semua file pyc di folder tingkat mana saja **/*.pyc # Hanya abaikan file TODO.md yang ada di root folder saja /TODO.md # Pengecualian: jangan abaikan file ini (negasi) *.log !important.log # Abaikan semua isi folder docs kecuali file README.md docs/* !docs/README.md # Abaikan folder temp di kedalaman folder tingkat satu saja */temp/ # Abaikan folder temp di kedalaman tingkat mana saja **/temp/ Contoh Isi .gitignore yang Umum Dipakai # === Package Dependencies === node_modules/ vendor/ .venv/ __pycache__/ # === Output Hasil Build === dist/ build/ *.o *.pyc # === Setingan IDE / Text Editor === .idea/ .vscode/ *.swp *.swo *~ .DS_Store # === File Environment (Rahasia) === .env .env.local .env.*.local # === Log File === *.log logs/ # === OS Files === .DS_Store Thumbs.db # === Folder Pengujian (Testing) === coverage/ .nyc_output/ # === File Kunci Rahasia (JANGAN PERNAH DI-COMMIT) === *.pem *.key *.p12 credentials.json Mengelola File yang Terlanjur Dilacak # Berhenti melacak file tapi biarkan filenya tetap ada di komputer git rm --cached secrets.env # Setelah ini, tambahkan secrets.env ke dalam file .gitignore # Berhenti melacak satu folder utuh git rm -r --cached node_modules/ # Cara bersihkan cache tracking setelah mengedit isi .gitignore: git rm -r --cached . git add . git commit -m \u0026#34;Apply update aturan .gitignore baru\u0026#34; File .gitignore Global Bermanfaat untuk mengabaikan file sampah OS di semua repositori lokal kamu:\n# Bikin file gitignore global echo \u0026#34;.DS_Store\\n*.swp\\n.idea/\u0026#34; \u0026gt;\u0026gt; ~/.gitignore_global # Beritahu Git untuk memakai file gitignore global tersebut git config --global core.excludesfile ~/.gitignore_global Memeriksa Status Abaikan File # Cek aturan mana di .gitignore yang mengabaikan file ini git check-ignore -v debug.log # Contoh output: .gitignore:3:*.log debug.log # Tampilkan daftar seluruh file yang diabaikan git status --ignored Worktrees Worktree membolehkan kamu checkout beberapa branch secara bersamaan di folder yang terpisah. Jadi kamu tidak perlu stash atau buru-buru commit kerjaan setengah matang hanya untuk pindah branch sejenak.\nPerintah Dasar Worktree # Bikin folder worktree baru untuk suatu branch git worktree add ../hotfix-login hotfix/login-bug # Sekarang struktur folder kamu: # /project → branch main aktif (repositori asal) # /hotfix-login → branch hotfix/login-bug aktif (terpisah) # Bikin folder worktree sekaligus bikin branch baru git worktree add -b feature/new-api ../new-api main Mengelola Worktree # Tampilkan daftar seluruh worktree aktif git worktree list # Contoh output: # /Users/sofyan/project abc1234 [main] # /Users/sofyan/hotfix-login def5678 [hotfix/login-bug] # Hapus folder worktree setelah selesai dipakai git worktree remove ../hotfix-login # Bersihkan metadata worktree yang foldernya terhapus manual git worktree prune Skenario Nyata Penggunaan Worktree # Kamu lagi asyik bikin fitur baru, tiba-tiba ada bug kritis di production # Dibandingkan harus stash-switch branch: git worktree add ../emergency-fix -b hotfix/prod-crash main # Pindah ke folder darurat tersebut dan bereskan bug-nya cd ../emergency-fix # ... lakukan perbaikan ... git add . git commit -m \u0026#34;Fix null pointer in payment processing\u0026#34; git push origin hotfix/prod-crash # Balik lagi ke folder project utama kamu tadi — tanpa stashing atau kehilangan fokus cd ../project # Branch fitur kamu tetap di kondisi terakhir saat kamu tinggalkan # Setelah kelar, bersihkan folder daruratnya git worktree remove ../emergency-fix Bisect (Pencarian Bug Binary) git bisect melakukan pencarian binary search pada riwayat commit untuk mendeteksi commit mana yang pertama kali membawa bug. Jadi kamu tidak usah mengecek commit satu per satu secara manual.\nCara Manual Bisect # Mulai bisect git bisect start # Tandai commit saat ini berstatus rusak/ada bug (bad) git bisect bad # Tandai commit lama di masa lalu yang statusnya normal/tidak ada bug (good) git bisect good v1.0.0 # Git bakal otomatis checkout ke commit pertengahan. Tes aplikasinya, lalu: git bisect good # kalau versi ini normal # atau git bisect bad # kalau versi ini rusak / ada bug Git bakal terus membelah sisa commit sampai akhirnya mendeteksi:\n# abc1234 is the first bad commit # commit abc1234 # Author: Seseorang # Date: ... # Message: Refactor payment module Setelah ketemu biang keroknya, kembalikan posisi branch ke kondisi awal:\ngit bisect reset Cara Otomatis Bisect Kalau kamu punya script testing yang exit codenya 0 untuk sukses (good) dan non-zero untuk error (bad):\ngit bisect start git bisect bad HEAD git bisect good v1.0.0 # Suruh Git mengetes tiap commit secara otomatis pakai script tadi git bisect run npm test # Atau pakai script kustom kamu sendiri git bisect run ./test-login.sh # Git bakal otomatis mencari commit yang merusak kodenya sendiri sampai selesai Memulai dengan Rentang Commit # Kalau kamu tahu bug-nya ada di antara commit HEAD dan abc1234 git bisect start HEAD abc1234 # ini sama saja dengan: # git bisect start # git bisect bad HEAD # git bisect good abc1234 Contoh Kasus Praktis # Menu login rusak. Kemarin pas rilis (v2.3.0) statusnya masih aman berjalan. git bisect start git bisect bad HEAD git bisect good v2.3.0 # Git berkata: \u0026#34;Bisecting: 23 revisions left to test (roughly 5 steps)\u0026#34; # Git checkout otomatis. Kamu jalankan test: npm test # Kalau test error → git bisect bad # Kalau test aman → git bisect good # Setelah sekitar 5 langkah: # \u0026#34;abc1234 is the first bad commit\u0026#34; # Ketemu! Sekarang kamu tahu persis bagian kode mana yang merusaknya. git bisect reset git show abc1234 # telusuri commit yang bersalah Workflow Praktis yang Sering Dipakai Workflow Branch Fitur (Feature Branch) Workflow paling umum yang sering dipakai di dalam tim:\n# 1. Pastikan main kamu sudah versi terbaru git switch main git pull # 2. Bikin branch fitur baru git switch -c feature/user-dashboard # 3. Mulai nulis kode (bebas commit beberapa kali) git add . git commit -m \u0026#34;Add dashboard layout\u0026#34; # ... kerja lagi ... git add . git commit -m \u0026#34;Add charts component\u0026#34; # ... kerja lagi ... git add . git commit -m \u0026#34;Connect dashboard to API\u0026#34; # 4. Sinkronkan branch kamu dengan update main terbaru git fetch origin git rebase origin/main # (selesaikan konflik jika ada) # 5. Rapikan riwayat commit sebelum diajukan ke Pull Request (PR) git rebase -i origin/main # Squash commit-commit kecil, perbaiki pesan commit yang kurang oke # 6. Push branch ke server remote git push -u origin feature/user-dashboard # 7. Setelah PR di-merge oleh tim, bersihkan branch lokalnya git switch main git pull git branch -d feature/user-dashboard Workflow Hotfix (Perbaikan Cepat Production) # 1. Bikin branch langsung dari main (atau tag rilis production aktif) git switch main git pull git switch -c hotfix/payment-crash # 2. Selesaikan perbaikan bug-nya git add . git commit -m \u0026#34;Fix null check in payment processing\u0026#34; # 3. Push dan buat PR git push -u origin hotfix/payment-crash # 4. Setelah digabungkan, pasang tag versi rilis baru git switch main git pull git tag -a v2.3.1 -m \u0026#34;Hotfix: payment crash\u0026#34; git push origin v2.3.1 # 5. Bersihkan branch hotfix-nya git branch -d hotfix/payment-crash git push origin --delete hotfix/payment-crash Merapikan Commit sebelum Membuat PR # Kamu punya commit lokal yang riwayat pesannya berantakan: # \u0026#34;Add feature\u0026#34; # \u0026#34;fix typo\u0026#34; # \u0026#34;WIP\u0026#34; # \u0026#34;actually fix it\u0026#34; # \u0026#34;review feedback\u0026#34; # Satukan semua commit kecil tadi ke dalam commit logis utama: git rebase -i origin/main # Di dalam editor, ubah daftarnya menjadi: pick a1b2c3d Add user notification system fixup e4f5g6h fix typo fixup i7j8k9l WIP fixup m0n1o2p actually fix it fixup q3r4s5t review feedback # Hasilnya: tersisa satu commit bersih berbunyi \u0026#34;Add user notification system\u0026#34; Menyinkronkan Repositori Fork # Tambahkan alamat remote repositori hulu/asli jika belum ada git remote add upstream https://github.com/original/repo.git # Ambil dan gabungkan perubahan dari upstream ke lokal main kamu git fetch upstream git switch main git merge upstream/main git push origin main # Rebase branch fitur kamu di atas main yang sudah terupdate tadi git switch feature/my-work git rebase main Memperbaiki Kesalahan Umum Salah menulis commit di branch main (seharusnya di branch fitur):\n# Batalkan commit terakhir tapi biarkan kodenya tetap aman git reset --soft HEAD~1 # Simpan kodenya sementara, lalu pindah branch dan terapkan kembali kodenya git stash git switch branch-fitur-yang-benar git stash pop git add . git commit -m \u0026#34;Pesan commit kamu\u0026#34; Ingin membatalkan commit yang telanjur di-push ke branch bersama:\n# Gunakan revert (aman, tidak merusak riwayat commit rekan kerja) git revert abc1234 git push Tidak sengaja menghapus branch lokal:\n# Cari hash commit terakhir di branch yang terhapus tadi git reflog # Bikin ulang branch-nya berdasarkan hash commit tersebut git branch branch-selamat abc1234 Tidak sengaja menjalankan git reset --hard:\n# Jangan panik — reflog siap menyelamatkanmu git reflog # Cari hash commit tepat sesaat sebelum reset dijalankan git reset --hard HEAD@{1} Merge salah jalan dan ingin dibatalkan:\n# Jika commit merge belum di-push ke server remote git reset --hard HEAD~1 # Jika commit merge sudah terlanjur di-push ke server remote git revert -m 1 hash-commit-merge git push Memecah Satu Commit Menjadi Dua Jika sebuah commit berisi perubahan yang terlalu banyak dan ingin kamu pisah:\n# Lakukan rebase interaktif, tandai commit target dengan status \u0026#39;edit\u0026#39; git rebase -i HEAD~3 # Di editor: ubah status \u0026#39;pick\u0026#39; menjadi \u0026#39;edit\u0026#39; pada commit yang mau dipecah # Git bakal berhenti di commit tersebut. Batalkan commit tapi pertahankan kodenya: git reset HEAD~1 # Sekarang tinggal masukkan kodenya satu per satu ke commit terpisah: git add src/model.js git commit -m \u0026#34;Add user model\u0026#34; git add src/controller.js git commit -m \u0026#34;Add user controller\u0026#34; # Lanjutkan proses rebase sampai selesai git rebase --continue Menjaga Kebersihan Working Directory # Cek daftar file sampah yang belum dilacak (uji coba dulu) git clean -n # Hapus file sampah yang belum dilacak dari repositori (eksekusi) git clean -f # Hapus file sampah DAN folder sampah yang belum dilacak git clean -fd # Hapus semua file sampah, folder sampah, termasuk file yang diabaikan di .gitignore git clean -fdx # Jalankan proses pembersihan secara interaktif satu per satu git clean -i Tabel Rangkuman Singkat Perintah Harian Perintah Aksi / Fungsi git status -sb Status singkat disertai info branch git add -p Masukkan perubahan kode ke stage secara interaktif git commit -m \u0026quot;pesan\u0026quot; Commit perubahan dengan pesan git commit --amend --no-edit Tambahkan file baru ke commit terakhir git pull --rebase Ambil update baru dengan metode rebase git push Unggah commit branch aktif ke server remote git switch -c nama_branch Bikin branch baru dan langsung pindah ke sana git switch - Pindah balik ke branch sebelumnya git stash Simpan sementara perubahan kode aktif git stash pop Terapkan kembali perubahan kode dari stash terakhir git log --oneline -10 Lihat 10 log commit terakhir secara ringkas git diff --staged Cek perbedaan kode yang sudah ada di stage Urusan Branching Perintah Aksi / Fungsi git branch Tampilkan daftar branch lokal git branch -a Tampilkan daftar seluruh branch (lokal + remote) git switch -c nama Bikin branch baru dan langsung pindah git branch -d nama Hapus branch lokal yang sudah di-merge git branch -D nama Hapus paksa branch lokal yang belum di-merge git branch -m nama_baru Ubah nama branch aktif saat ini git push origin --delete nama Hapus branch di server remote Pembatalan Kode (Undoing) Perintah Aksi / Fungsi git restore nama_file Buang perubahan kode di working directory git restore --staged nama_file Keluarkan file dari staging area (unstage) git reset --soft HEAD~1 Batalkan commit, simpan filenya di stage git reset HEAD~1 Batalkan commit, keluarkan filenya dari stage git reset --hard HEAD~1 Batalkan commit, buang seluruh perubahan kode git revert hash_commit Batalkan efek commit masa lalu lewat commit baru git reflog Tampilkan riwayat lengkap perpindahan HEAD git cherry-pick hash_commit Terapkan commit tertentu dari branch sebelah Riwayat Sejarah (History) Perintah Aksi / Fungsi git log --oneline --graph --all Tampilkan grafik visual alur commit repositori git log --author=\u0026quot;nama\u0026quot; Filter log commit berdasarkan nama pembuatnya git log -S \u0026quot;kode\u0026quot; Cari commit berdasarkan penambahan/penghapusan kode git log -- nama_file Tampilkan log commit khusus untuk file ini saja git blame nama_file Lihat siapa pembuat terakhir tiap baris kode file git show hash_commit Detail isi data dan diff dari commit tertentu git diff A..B Bandingkan kode di branch A dengan branch B Urusan Remote Server Perintah Aksi / Fungsi git remote -v Tampilkan daftar alamat remote repositori git fetch --prune Ambil update server sekaligus bersihkan branch mati git pull --rebase Ambil update server dengan metode rebase git push -u origin branch Push branch sekaligus setting default tracking git push --force-with-lease Push paksa yang aman (tidak menimpa kerjaan teman) Fitur Lanjutan (Advanced) Perintah Aksi / Fungsi git rebase -i HEAD~n Rebase interaktif untuk n commit terakhir git bisect start Jalankan binary search pencari biang bug git worktree add path branch Buka branch lain di folder terpisah bersamaan git stash -u Stash beserta file baru yang belum terlacak git clean -fd Hapus file sampah dan folder sampah tak terlacak git tag -a v1.0 -m \u0026quot;msg\u0026quot; Bikin tag beranotasi untuk rilis versi git commit --fixup=hash Bikin commit perbaikan khusus untuk autosquash git rebase --autosquash Jalankan autosquash otomatis saat rebase Cheatsheet ini mencakup perintah Git yang bakal kamu pakai 99% dari waktu kerja kamu. Kuasai perintah dasar ini, dan kamu bakal bisa menangani workflow apa pun.\n","permalink":"https://waldy.id/git/","summary":"\u003cp\u003eGit itu melacak \u003cstrong\u003esnapshot\u003c/strong\u003e dari project kamu, bukan sekadar perbedaan baris kode (diff). Setiap commit adalah gambaran utuh dari seluruh project kamu pada momen tersebut. Memahami konsep ini bakal mengubah cara kamu berpikir tentang branching, merging, dan history.\u003c/p\u003e\n\u003cp\u003eCheatsheet ini didesain buat kerjaan development sehari-hari — tipe panduan yang bakal benar-benar kamu bookmark dan buka lagi terus-menerus.\u003c/p\u003e\n\u003chr\u003e\n\u003ch2 id=\"konsep-utama\"\u003eKonsep Utama\u003c/h2\u003e\n\u003cp\u003eSebelum mulai menjalankan perintah-perintah Git, kamu harus paham dulu tiga area utama di Git:\u003c/p\u003e","title":"Cheatsheet Lengkap Git"},{"content":"Regular Expressions (regex) itu alat pencocokan pola (pattern-matching) yang ada di hampir semua bahasa pemrograman, text editor, dan command-line tool. Regex membantumu mencari, memvalidasi, mengekstrak, dan mengubah teks dengan bahasa pola yang ringkas.\nCheatsheet ini didesain sebagai referensi harian kamu — tidak cuma berisi daftar sintaks, tapi juga contoh-contoh praktis yang bakal benar-benar kamu pakai saat memparsing log, memvalidasi input, merefaktorkan kode, atau mencari teks di dalam codebase.\nApa itu Regex? Regular Expression (regex) adalah urutan karakter yang membentuk suatu pola pencarian. Kamu memberikan pola tersebut ke engine regex, dan dia bakal mencarikan teks yang cocok dengan pola itu.\nPola (Pattern): \\d{3}-\\d{4} Teks Cocok: \u0026#34;555-1234\u0026#34; di dalam kalimat \u0026#34;Hubungi 555-1234 untuk info\u0026#34; Regex dipakai di mana-mana:\nValidasi — cek apakah format email atau nomor telepon sudah benar Pencarian (Search) — temukan semua URL di dalam sebuah dokumen Ekstraksi (Extract) — ambil data tanggal dari baris log Penggantian (Replace) — ubah nama variabel di seluruh codebase Pemisahan (Split) — pecah baris data CSV menjadi kolom-kolom Sintaks regex sebagian besar standar di berbagai bahasa pemrograman (kompatibel dengan PCRE), tapi Vim punya dialeknya sendiri. Cheatsheet ini membahas keduanya.\nPencocokan Dasar (Basic Matching) Di tingkat paling sederhana, regex itu cuma berupa string biasa. Pola error bakal mencocokkan potongan kata \u0026ldquo;error\u0026rdquo; di mana pun kata itu muncul.\nPola (Pattern): error Teks: \u0026#34;Terjadi error pada server\u0026#34; Hasil Cocok: \u0026#34;error\u0026#34; (posisi karakter ke 8-12) Sensitivitas Huruf (Case Sensitivity) Secara default, pencarian regex itu sensitif huruf kapital (case-sensitive):\nPola (Pattern): Error Teks: \u0026#34;error\u0026#34; → tidak cocok Teks: \u0026#34;Error\u0026#34; → cocok Teks: \u0026#34;ERROR\u0026#34; → tidak cocok Untuk mencari tanpa memedulikan huruf besar/kecil, gunakan flag i (dibahas di bagian Flag Umum):\nPola (Pattern): /error/i Teks Cocok: \u0026#34;error\u0026#34;, \u0026#34;Error\u0026#34;, \u0026#34;ERROR\u0026#34;, \u0026#34;eRrOr\u0026#34; Mencocokkan Karakter Berurutan Pola dicocokkan dari kiri ke kanan, karakter demi karakter:\nPola (Pattern): 404 Teks: \u0026#34;HTTP 404 Not Found\u0026#34; Hasil Cocok: \u0026#34;404\u0026#34; (posisi karakter ke 5-7) Pola (Pattern): not found Teks: \u0026#34;HTTP 404 Not Found\u0026#34; → tidak cocok (karena beda huruf kapital) Pola (Pattern): /not found/i → cocok dengan \u0026#34;Not Found\u0026#34; Karakter Khusus (Metacharacters) Karakter-karakter ini punya arti khusus di regex. Kalau kamu mau mencari karakter ini secara harfiah, kamu harus menambah garis miring terbalik (backslash) \\ di depannya (escape).\nKarakter Arti Contoh Teks Cocok . Karakter apa saja (kecuali baris baru) c.t \u0026ldquo;cat\u0026rdquo;, \u0026ldquo;cut\u0026rdquo;, \u0026ldquo;c9t\u0026rdquo; ^ Awal baris/string ^Dari: \u0026ldquo;Dari:\u0026rdquo; di awal baris $ Akhir baris/string \\.js$ \u0026ldquo;app.js\u0026rdquo; di akhir baris | Pilihan (ATAU / OR) cat|dog \u0026ldquo;cat\u0026rdquo; atau \u0026ldquo;dog\u0026rdquo; \\ Karakter escape (untuk mencari simbol literal) \\. karakter titik \u0026ldquo;.\u0026rdquo; literal ( ) Pengelompokan (Grouping) (ab)+ \u0026ldquo;ab\u0026rdquo;, \u0026ldquo;abab\u0026rdquo; [ ] Kelas karakter (Character class) [aeiou] semua huruf vokal { } Batasan jumlah (Quantifier range) \\d{3} tiga digit angka * Nol kali atau lebih bo* \u0026ldquo;b\u0026rdquo;, \u0026ldquo;bo\u0026rdquo;, \u0026ldquo;boo\u0026rdquo; + Satu kali atau lebih bo+ \u0026ldquo;bo\u0026rdquo;, \u0026ldquo;boo\u0026rdquo;, \u0026ldquo;booo\u0026rdquo; ? Nol atau satu kali colou?r \u0026ldquo;color\u0026rdquo;, \u0026ldquo;colour\u0026rdquo; Cara Meng-escape Karakter Khusus Kalau kamu butuh mencari karakter khusus secara harfiah, taruh \\ di depannya:\nPola (Pattern): \\$100\\.00 Teks: \u0026#34;Harga: $100.00\u0026#34; Hasil Cocok: \u0026#34;$100.00\u0026#34; Pola (Pattern): index\\.html Teks: \u0026#34;Buka index.html dari folder /var/www\u0026#34; Hasil Cocok: \u0026#34;index.html\u0026#34; Pola (Pattern): file\\[0\\] Teks: \u0026#34;Akses variabel file[0] di array\u0026#34; Hasil Cocok: \u0026#34;file[0]\u0026#34; Karakter Titik . Titik mencocokkan satu karakter apa saja kecuali baris baru (kecuali flag s aktif):\nPola (Pattern): 192\\.168\\.0\\.. Teks: \u0026#34;192.168.0.1\u0026#34; → cocok Teks: \u0026#34;192.168.0.A\u0026#34; → cocok Teks: \u0026#34;192x168.0.1\u0026#34; → tidak cocok (karena titik pertama di-escape, jadi wajib karakter titik asli) Kesalahan umum adalah lupa meng-escape karakter titik saat ingin mencari titik asli — selalu escape di URL, alamat IP, dan nama file:\nSalah: 192.168.0.1 → juga bakal cocok dengan \u0026#34;192x168y0z1\u0026#34; Benar: 192\\.168\\.0\\.1 → hanya cocok dengan \u0026#34;192.168.0.1\u0026#34; Kelas Karakter (Character Classes) Kelas karakter mencocokkan satu karakter dari kumpulan yang sudah ditentukan.\nKumpulan Dasar [abc] → cocok dengan \u0026#34;a\u0026#34;, \u0026#34;b\u0026#34;, atau \u0026#34;c\u0026#34; [0123] → cocok dengan \u0026#34;0\u0026#34;, \u0026#34;1\u0026#34;, \u0026#34;2\u0026#34;, atau \u0026#34;3\u0026#34; [aeiou] → cocok dengan huruf vokal kecil Rentang Karakter (Ranges) [a-z] → huruf kecil dari a sampai z [A-Z] → huruf besar dari A sampai Z [0-9] → angka dari 0 sampai 9 [a-zA-Z] → huruf apa saja (besar maupun kecil) [a-zA-Z0-9] → huruf atau angka (alfanumerik) Negasi (Pengecualian) Tanda caret ^ di dalam kurung siku berarti negasi (mencocokkan karakter yang tidak ada di daftar):\n[^0-9] → karakter apa saja yang BUKAN angka [^aeiou] → karakter apa saja yang BUKAN huruf vokal kecil [^ ] → karakter apa saja yang BUKAN spasi Singkatan Kelas Karakter Singkatan Setara Dengan Arti \\d [0-9] Digit angka \\D [^0-9] Selain digit angka \\w [a-zA-Z0-9_] Karakter kata (huruf, angka, underscore) \\W [^a-zA-Z0-9_] Selain karakter kata \\s [ \\t\\r\\n\\f] Karakter spasi (spasi, tab, baris baru, dll) \\S [^ \\t\\r\\n\\f] Selain karakter spasi Contoh Praktis Mencocokkan kode warna hex CSS:\nPola (Pattern): #[0-9a-fA-F]{6} Teks Cocok: \u0026#34;#ff5733\u0026#34;, \u0026#34;#00AABB\u0026#34;, \u0026#34;#123def\u0026#34; Tidak Cocok: \u0026#34;#xyz\u0026#34;, \u0026#34;#12\u0026#34; Mencocokkan nama class CSS (harus diawali huruf atau underscore):\nPola (Pattern): [a-zA-Z_][\\w-]* Teks Cocok: \u0026#34;nav-bar\u0026#34;, \u0026#34;_hidden\u0026#34;, \u0026#34;Container\u0026#34; Mencocokkan username (alfanumerik, underscore, panjang 3-16 karakter):\nPola (Pattern): ^[a-zA-Z0-9_]{3,16}$ Teks Cocok: \u0026#34;john_doe\u0026#34;, \u0026#34;user42\u0026#34;, \u0026#34;dev\u0026#34; Tidak Cocok: \u0026#34;ab\u0026#34;, \u0026#34;user name\u0026#34;, \u0026#34;username_yang_kepanjangan_banget\u0026#34; Karakter Khusus di Dalam Kelas Karakter Di dalam [ ], sebagian besar karakter khusus kehilangan makna magisnya. Hanya karakter berikut yang punya arti khusus:\nKarakter Aturan ] Penutup kelas — escape menjadi \\] atau letakkan di paling awal []abc] \\ Karakter escape — tetap berfungsi untuk meng-escape ^ Negasi — hanya berfungsi jika ditaruh di karakter pertama setelah [ - Rentang — escape menjadi \\- atau letakkan di paling awal/akhir [-abc] atau [abc-] Pola (Pattern): [$@#!] Teks Cocok: salah satu dari \u0026#34;$\u0026#34;, \u0026#34;@\u0026#34;, \u0026#34;#\u0026#34;, \u0026#34;!\u0026#34; — tidak perlu di-escape Kelas Karakter POSIX (Terminal / grep) POSIX Setara Dengan Arti [:alpha:] [a-zA-Z] Huruf [:digit:] [0-9] Angka [:alnum:] [a-zA-Z0-9] Alfanumerik [:space:] [ \\t\\r\\n\\f\\v] Spasi dan sejenisnya [:upper:] [A-Z] Huruf besar [:lower:] [a-z] Huruf kecil [:punct:] Simbol tanda baca Karakter simbol Digunakan di dalam kurung siku: [[:digit:]] — perhatikan kurung sikunya double.\nQuantifiers (Penentu Jumlah) Quantifiers mengatur berapa kali elemen sebelumnya boleh muncul.\nQuantifier Arti Contoh Teks Cocok * 0 kali atau lebih https?://.* URL apa saja yang diawali http atau https + 1 kali atau lebih \\d+ \u0026ldquo;1\u0026rdquo;, \u0026ldquo;42\u0026rdquo;, \u0026ldquo;99999\u0026rdquo; ? 0 atau 1 kali colou?r \u0026ldquo;color\u0026rdquo;, \u0026ldquo;colour\u0026rdquo; {n} Tepat n kali \\d{4} \u0026ldquo;2026\u0026rdquo;, \u0026ldquo;1999\u0026rdquo; {n,} Minimal n kali atau lebih \\w{8,} Kata dengan 8 karakter atau lebih {n,m} Antara n sampai m kali \\d{1,3} \u0026ldquo;1\u0026rdquo;, \u0026ldquo;42\u0026rdquo;, \u0026ldquo;255\u0026rdquo; Rakus (Greedy) vs. Malas (Lazy / Non-Greedy) Secara default, quantifiers itu bersifat greedy (rakus) — mereka bakal mencocokkan teks sebanyak mungkin yang bisa diambil:\nPola (Pattern): \u0026#34;.+\u0026#34; Teks: Dia berkata \u0026#34;halo\u0026#34; dan \u0026#34;dadah\u0026#34; Greedy (Rakus): \u0026#34;halo\u0026#34; dan \u0026#34;dadah\u0026#34; ← mencocokkan dari kutip pertama sampai kutip terakhir Tambahkan tanda ? setelah quantifier untuk membuatnya bersifat lazy (malas) — mencocokkan teks sesedikit mungkin:\nPola (Pattern): \u0026#34;.+?\u0026#34; Teks: Dia berkata \u0026#34;halo\u0026#34; dan \u0026#34;dadah\u0026#34; Lazy (Malas): \u0026#34;halo\u0026#34; dan \u0026#34;dadah\u0026#34; ← menghasilkan dua kecocokan terpisah Greedy (Rakus) Lazy (Malas) Arti * *? 0 kali atau lebih (paling pendek) + +? 1 kali atau lebih (paling pendek) ? ?? 0 atau 1 kali (pilih yang 0 jika bisa) {n,m} {n,m}? Antara n sampai m kali (paling pendek) Contoh Kasus Greedy vs. Lazy Mengambil isi tag HTML:\nGreedy: \u0026lt;.+\u0026gt; Teks: \u0026lt;span\u0026gt;Halo\u0026lt;/span\u0026gt; Cocok: \u0026lt;span\u0026gt;Halo\u0026lt;/span\u0026gt; ← mencocokkan dari \u0026lt; pertama sampai \u0026gt; terakhir Lazy: \u0026lt;.+?\u0026gt; Teks: \u0026lt;span\u0026gt;Halo\u0026lt;/span\u0026gt; Cocok: \u0026lt;span\u0026gt; dan \u0026lt;/span\u0026gt; ← dua kecocokan terpisah Mengambil nilai JSON:\nGreedy: \u0026#34;value\u0026#34;: \u0026#34;(.+)\u0026#34; Teks: \u0026#34;value\u0026#34;: \u0026#34;halo\u0026#34;, \u0026#34;other\u0026#34;: \u0026#34;dunia\u0026#34; Cocok: halo\u0026#34;, \u0026#34;other\u0026#34;: \u0026#34;dunia ← terlalu rakus memakan tanda kutip berikutnya Lazy: \u0026#34;value\u0026#34;: \u0026#34;(.+?)\u0026#34; Teks: \u0026#34;value\u0026#34;: \u0026#34;halo\u0026#34;, \u0026#34;other\u0026#34;: \u0026#34;dunia\u0026#34; Cocok: halo ← benar Anchors (Jangkar Posisi) Anchors tidak mencocokkan karakter — melainkan mencocokkan posisi di dalam teks.\nAnchor Arti Contoh ^ Awal string (atau awal baris jika flag m aktif) ^#!/bin/bash $ Akhir string (atau akhir baris jika flag m aktif) \\.py$ \\b Batas kata (word boundary) \\berror\\b \\B Selain batas kata \\Berror\\B Awal ^ dan Akhir $ Pola (Pattern): ^# Teks: \u0026#34;# Ini heading\u0026#34; → cocok (karena diawali #) Teks: \u0026#34;Bukan # heading\u0026#34; → tidak cocok Pola (Pattern): ;$ Teks: \u0026#34;let x = 5;\u0026#34; → cocok (karena diakhiri ;) Teks: \u0026#34;let x = 5\u0026#34; → tidak cocok Kombinasikan keduanya untuk validasi teks utuh:\nPola (Pattern): ^\\d{5}$ Teks Cocok: \u0026#34;90210\u0026#34; (tepat 5 digit angka saja, tanpa teks lain) Tidak Cocok: \u0026#34;KODE: 90210\u0026#34; (ada teks tambahan di depannya) Batas Kata \\b Batas kata adalah posisi di antara karakter kata \\w dan karakter non-kata \\W (atau awal/akhir string):\nPola (Pattern): \\berror\\b Teks: \u0026#34;An error occurred\u0026#34; → cocok dengan \u0026#34;error\u0026#34; Teks: \u0026#34;RuntimeError thrown\u0026#34; → tidak cocok (\u0026#34;error\u0026#34; ada di dalam kata lain) Teks: \u0026#34;error_code is set\u0026#34; → tidak cocok (karena \u0026#34;_\u0026#34; dianggap karakter kata) Ini berguna banget buat mencari kata kunci di file kode agar tidak salah deteksi:\nPola (Pattern): \\bclass\\b Teks Cocok: \u0026#34;class User\u0026#34; (keyword class asli) Tidak Cocok: \u0026#34;className\u0026#34; (bagian dari kata lain) Tidak Cocok: \u0026#34;subclass\u0026#34; (bagian dari kata lain) Pola (Pattern): \\buser_id\\b Teks Cocok: \u0026#34;SELECT user_id FROM\u0026#34; (nama variabel presisi) Tidak Cocok: \u0026#34;user_id_backup\u0026#34; (karena tersambung underscore) Groups dan Capturing (Pengelompokan \u0026amp; Penangkapan) Tanda kurung () membuat grup. Grup punya dua fungsi: mengelompokkan pola (buat quantifier/pilihan) dan menangkap teks hasil pencocokan untuk dipakai kembali nanti.\nCapturing Group Dasar Pola (Pattern): (\\d{4})-(\\d{2})-(\\d{2}) Teks: \u0026#34;Tanggal: 2026-06-17\u0026#34; Grup 0: \u0026#34;2026-06-17\u0026#34; (seluruh teks cocok) Grup 1: \u0026#34;2026\u0026#34; (tahun) Grup 2: \u0026#34;06\u0026#34; (bulan) Grup 3: \u0026#34;17\u0026#34; (hari) Non-Capturing Group (?:...) Digunakan saat kamu butuh mengelompokkan pola tapi tidak perlu menangkap hasilnya:\nPola (Pattern): (?:https?|ftp)://[\\w.-]+ Teks: \u0026#34;Buka https://example.com\u0026#34; Hasil Cocok: \u0026#34;https://example.com\u0026#34; Sintaks (?:...) mengelompokkan https? dan ftp untuk pilihan (ATAU) tanpa membuat tangkapan grup baru. Ini lebih cepat dan menjaga urutan index grup kamu tetap rapi.\nNamed Capturing Group (Tangkapan Grup Bernama) Membuat grup tangkapan punya nama khusus agar regex kamu lebih mudah dibaca:\n# Sintaks Python Pola: (?P\u0026lt;year\u0026gt;\\d{4})-(?P\u0026lt;month\u0026gt;\\d{2})-(?P\u0026lt;day\u0026gt;\\d{2}) # Sintaks JavaScript Pola: (?\u0026lt;year\u0026gt;\\d{4})-(?\u0026lt;month\u0026gt;\\d{2})-(?\u0026lt;day\u0026gt;\\d{2}) Teks: \u0026#34;2026-06-17\u0026#34; year → \u0026#34;2026\u0026#34; month → \u0026#34;06\u0026#34; day → \u0026#34;17\u0026#34; Backreferences (Referensi Balik) \\1, \\2 Merujuk kembali hasil tangkapan grup sebelumnya di dalam pola regex yang sama:\nPola (Pattern): \u0026lt;(\\w+)\u0026gt;.*?\u0026lt;/\\1\u0026gt; Teks: \u0026#34;\u0026lt;div\u0026gt;Halo\u0026lt;/div\u0026gt;\u0026#34; Grup 1: \u0026#34;div\u0026#34; \\1: bakal mencocokkan kata \u0026#34;div\u0026#34; lagi di tag penutupnya Hasil Cocok: \u0026#34;\u0026lt;div\u0026gt;Halo\u0026lt;/div\u0026gt;\u0026#34; Ini memastikan tag pembuka dan penutupnya sama persis:\nPola (Pattern): \u0026lt;(\\w+)\u0026gt;.*?\u0026lt;/\\1\u0026gt; Teks: \u0026#34;\u0026lt;div\u0026gt;Halo\u0026lt;/span\u0026gt;\u0026#34; → tidak cocok (karena div ≠ span) Mencari kata yang ditulis double (contoh kasus klasik):\nPola (Pattern): \\b(\\w+)\\s+\\1\\b Teks: \u0026#34;hari ini ini saya belajar\u0026#34; Hasil Cocok: \u0026#34;ini ini\u0026#34; Alternation (Pilihan / OR) Simbol pipa | berfungsi sebagai ATAU. Simbol ini punya prioritas paling rendah di antara semua operator regex, jadi dia bakal membagi seluruh pola di sebelah kiri dan kanannya seutuhnya:\nPola (Pattern): cat|dog Teks Cocok: \u0026#34;cat\u0026#34; atau \u0026#34;dog\u0026#34; Pola (Pattern): error|warning|info Teks Cocok: \u0026#34;error\u0026#34;, \u0026#34;warning\u0026#34;, atau \u0026#34;info\u0026#34; Alternation dengan Pengelompokan Jika tidak dikelompokkan, | bakal membagi seluruh pola. Gunakan kurung untuk membatasinya:\nPola (Pattern): gray|grey → cocok dengan \u0026#34;gray\u0026#34; atau \u0026#34;grey\u0026#34; Lebih Rapi: gr(a|e)y → hasil sama, lebih spesifik batasnya Bahkan: gr[ae]y → hasil sama, terbaik jika cuma 1 karakter beda Contoh Praktis: Ekstensi File Pola (Pattern): \\.(js|ts|jsx|tsx)$ Teks Cocok: \u0026#34;App.tsx\u0026#34;, \u0026#34;index.js\u0026#34;, \u0026#34;utils.ts\u0026#34; Tidak Cocok: \u0026#34;style.css\u0026#34;, \u0026#34;README.md\u0026#34; Urutan Pilihan itu Penting Engine regex mencoba pilihan dari kiri ke kanan dan bakal berhenti di kecocokan pertama:\nPola (Pattern): http|https Teks: \u0026#34;https://example.com\u0026#34; Hasil Cocok: \u0026#34;http\u0026#34; ← berhenti di sini, tidak pernah mencoba \u0026#34;https\u0026#34; Solusi: https? ← pendekatan lebih baik Atau: https|http ← taruh pilihan yang lebih panjang di kiri Lookahead dan Lookbehind (Peneropongan Posisi) Lookarounds adalah zero-width assertions — mereka mengecek apakah ada pola lain di depan atau di belakang posisi aktif saat ini, tanpa memakan karakter teks tersebut. Hasil peneropongan tidak akan masuk ke output kecocokan teks.\nPositive Lookahead (?=...) \u0026ldquo;Cocokkan X hanya jika di depannya ada Y\u0026rdquo;:\nPola (Pattern): \\d+(?= rupiah) Teks: \u0026#34;Harganya 100 rupiah\u0026#34; Hasil Cocok: \u0026#34;100\u0026#34; (kata \u0026#34; rupiah\u0026#34; cuma diteropong saja, tidak ikut diambil) Pola (Pattern): \\w+(?=\\() Teks: \u0026#34;Jalankan fungsi getData() di sini\u0026#34; Hasil Cocok: \u0026#34;getData\u0026#34; (kata yang di depannya langsung diikuti tanda kurung buka) Negative Lookahead (?!...) \u0026ldquo;Cocokkan X hanya jika di depannya BUKAN Y\u0026rdquo;:\nPola (Pattern): \\d{3}(?!-) Teks: \u0026#34;555-1234 dan 9990\u0026#34; Hasil Cocok: \u0026#34;999\u0026#34; (tiga digit yang di depannya bukan tanda strip) Tidak Cocok: \u0026#34;555\u0026#34; (karena di depannya ada strip) Positive Lookbehind (?\u0026lt;=...) \u0026ldquo;Cocokkan X hanya jika di belakangnya ada Y\u0026rdquo;:\nPola (Pattern): (?\u0026lt;=\\$)\\d+(\\.\\d{2})? Teks: \u0026#34;Total: $49.99\u0026#34; Hasil Cocok: \u0026#34;49.99\u0026#34; (angka yang di belakangnya ada simbol $, tapi $ tidak ikut diambil) Negative Lookbehind (?\u0026lt;!...) \u0026ldquo;Cocokkan X hanya jika di belakangnya BUKAN Y\u0026rdquo;:\nPola (Pattern): (?\u0026lt;!un)happy Teks: \u0026#34;I am happy\u0026#34; → cocok dengan \u0026#34;happy\u0026#34; Teks: \u0026#34;I am unhappy\u0026#34; → tidak cocok (karena di belakang \u0026#34;happy\u0026#34; ada kata \u0026#34;un\u0026#34;) Mengombinasikan Lookarounds Validasi Password — harus ada minimal satu angka, satu huruf besar, satu huruf kecil, dan panjang minimal 8 karakter:\nPola (Pattern): ^(?=.*\\d)(?=.*[a-z])(?=.*[A-Z]).{8,}$ Penjelasan:\n(?=.*\\d) — di depan sana, wajib ada angka (?=.*[a-z]) — di depan sana, wajib ada huruf kecil (?=.*[A-Z]) — di depan sana, wajib ada huruf besar .{8,} — total panjang minimal 8 karakter apa saja Tabel Rangkuman Peneropongan Sintaks Nama Arti (?=...) Positive lookahead Di depannya ada \u0026hellip; (?!...) Negative lookahead Di depannya BUKAN \u0026hellip; (?\u0026lt;=...) Positive lookbehind Di belakangnya ada \u0026hellip; (?\u0026lt;!...) Negative lookbehind Di belakangnya BUKAN \u0026hellip; Flag Umum Flag mengubah cara engine regex menafsirkan pola pencarian.\nFlag Nama Efek g Global Cari semua kecocokan, jangan berhenti di hasil pertama i Case-insensitive Mengabaikan sensitivitas huruf besar/kecil m Multiline Membuat ^ dan $ berlaku per awal/akhir baris baru, bukan seluruh file s Dotall / Single-line Membuat karakter titik . bisa mencocokkan baris baru (\\n) u Unicode Menangani karakter Unicode (pada JS) x Extended / Verbose Mengabaikan spasi kosong di pola dan membolehkan komentar (Python, PCRE) Flag Global g // Tanpa g — cuma dapat kecocokan pertama \u0026#34;aaa\u0026#34;.match(/a/) // [\u0026#34;a\u0026#34;] // Pakai g — dapat semua kecocokan \u0026#34;aaa\u0026#34;.match(/a/g) // [\u0026#34;a\u0026#34;, \u0026#34;a\u0026#34;, \u0026#34;a\u0026#34;] Flag Multiline m Teks: \u0026#34;Baris 1\\nBaris 2\\nBaris 3\u0026#34; Tanpa m: ^Baris → hanya cocok dengan \u0026#34;Baris 1\u0026#34; di awal teks utama Pakai m: ^Baris → cocok dengan \u0026#34;Baris 1\u0026#34;, \u0026#34;Baris 2\u0026#34;, dan \u0026#34;Baris 3\u0026#34; (awal tiap baris) Pola Praktis yang Sering Dipakai Email (versi simpel) Pola (Pattern): ^[\\w.+-]+@[\\w-]+\\.[\\w.-]+$ ✓ user@example.com ✓ john.doe+tag@company.co.uk ✓ admin@sub.domain.org ✗ @example.com ✗ user@ ✗ user@.com URL Pola (Pattern): https?://[\\w.-]+(?::\\d+)?(?:/[\\w./?%\u0026amp;=~#-]*)? ✓ https://example.com ✓ http://api.example.com:8080/v1/users?page=2 ✓ https://en.wikipedia.org/wiki/Regular_expression ✗ ftp://files.example.com (butuh (?:https?|ftp) jika ingin mendukung ftp) ✗ example.com (tidak ada protokol http/https) Alamat IPv4 Ketat (0-255 per segmen): (?:25[0-5]|2[0-4]\\d|[01]?\\d\\d?)\\.(?:25[0-5]|2[0-4]\\d|[01]?\\d\\d?)\\.(?:25[0-5]|2[0-4]\\d|[01]?\\d\\d?)\\.(?:25[0-5]|2[0-4]\\d|[01]?\\d\\d?) ✓ 192.168.1.1 ✓ 10.0.0.255 ✗ 256.1.1.1 (versi ketat menolak angka di atas 255) ✗ 192.168.1 (kurang satu oktet) Tanggal (YYYY-MM-DD) Pola (Pattern): ^\\d{4}-(0[1-9]|1[0-2])-(0[1-9]|[12]\\d|3[01])$ ✓ 2026-06-17 ✓ 2000-01-31 ✗ 2026-13-01 (bulan tidak valid) ✗ 2026-06-32 (tanggal tidak valid) Regex di JavaScript JavaScript menggunakan sintaks /pola/flag secara literal atau class constructor RegExp.\nMembuat Objek Regex // Menggunakan sintaks literal (lebih disukai kalau polanya statis) const pattern = /\\d{3}-\\d{4}/g; // Menggunakan constructor (dipakai kalau polanya dinamis dari input user) const userInput = \u0026#34;error\u0026#34;; const pattern = new RegExp(`\\\\b${userInput}\\\\b`, \u0026#34;gi\u0026#34;); // Catatan: butuh double backslash \u0026#39;\\\\\u0026#39; di dalam string biasa Method test() — Cek Kecocokan Menghasilkan true atau false:\nconst emailRegex = /^[\\w.+-]+@[\\w-]+\\.[\\w.-]+$/; emailRegex.test(\u0026#34;user@example.com\u0026#34;); // true emailRegex.test(\u0026#34;bukan-email\u0026#34;); // false Method match() — Cari Hasil Cocok Menghasilkan array isi kecocokan (jika pakai flag g) atau detail kecocokan (tanpa g):\n// Semua hasil cocok const text = \u0026#34;Error ada di baris 42, 87, dan 156\u0026#34;; const numbers = text.match(/\\d+/g); // [\u0026#34;42\u0026#34;, \u0026#34;87\u0026#34;, \u0026#34;156\u0026#34;] // Hasil cocok tunggal dengan detail grup tangkapan const logLine = \u0026#34;[2026-06-17] ERROR: Koneksi ditolak\u0026#34;; const result = logLine.match(/\\[(\\d{4}-\\d{2}-\\d{2})\\]\\s(\\w+):\\s(.+)/); // result[0] = \u0026#34;[2026-06-17] ERROR: Koneksi ditolak\u0026#34; // result[1] = \u0026#34;2026-06-17\u0026#34; // result[2] = \u0026#34;ERROR\u0026#34; // result[3] = \u0026#34;Koneksi ditolak\u0026#34; Method replace() — Ganti Teks // Membersihkan spasi double const cleaned = \u0026#34; halo dunia \u0026#34;.replace(/\\s+/g, \u0026#34; \u0026#34;).trim(); // \u0026#34;halo dunia\u0026#34; // Menggunakan capture groups untuk tukar format tanggal const isoDate = \u0026#34;2026-06-17\u0026#34;; const usDate = isoDate.replace(/(\\d{4})-(\\d{2})-(\\d{2})/, \u0026#34;$2/$3/$1\u0026#34;); // \u0026#34;06/17/2026\u0026#34; // Menggunakan fungsi callback untuk penggantian dinamis const template = \u0026#34;Halo {name}, kamu punya {count} pesan baru\u0026#34;; const data = { name: \u0026#34;Alice\u0026#34;, count: 5 }; const result = template.replace(/\\{(\\w+)\\}/g, (match, key) =\u0026gt; data[key] ?? match); // \u0026#34;Halo Alice, kamu punya 5 pesan baru\u0026#34; Method split() — Potong String // Potong string CSV dengan spasi tidak teratur const line = \u0026#34;Alice, Bob, Charlie , Dave\u0026#34;; const names = line.split(/\\s*,\\s*/); // [\u0026#34;Alice\u0026#34;, \u0026#34;Bob\u0026#34;, \u0026#34;Charlie\u0026#34;, \u0026#34;Dave\u0026#34;] Regex di Python Python menggunakan module bawaan re.\nPenggunaan Dasar import re # Cari di mana saja di dalam teks result = re.search(r\u0026#34;\\d+\u0026#34;, \u0026#34;Order #12345 berhasil\u0026#34;) if result: print(result.group()) # \u0026#34;12345\u0026#34; print(result.start()) # 7 print(result.end()) # 12 # Cari khusus di awal string saja result = re.match(r\u0026#34;\\d+\u0026#34;, \u0026#34;12345 berhasil\u0026#34;) if result: print(result.group()) # \u0026#34;12345\u0026#34; Fungsi findall() — Ambil Semua Hasil text = \u0026#34;Suhu saat ini: 72°F, 68°F, 75°F\u0026#34; temps = re.findall(r\u0026#34;\\d+(?=°F)\u0026#34;, text) # [\u0026#39;72\u0026#39;, \u0026#39;68\u0026#39;, \u0026#39;75\u0026#39;] Fungsi sub() — Cari dan Ganti text = \u0026#34;Nama saya John Smith\u0026#34; swapped = re.sub(r\u0026#34;(\\w+)\\s(\\w+)\u0026#34;, r\u0026#34;\\2 \\1\u0026#34;, text) # \u0026#34;Nama saya Smith John\u0026#34; Regex di Vim Vim punya dialek regex sendiri. Perbedaan terbesarnya: secara default, banyak karakter khusus yang harus di-escape agar bisa berfungsi (kebalikan dari PCRE).\nOpsi Magic Mode Vim Mode Awalan Efek / Perilaku \\v (very magic) \\v Paling mirip PCRE — +, (, ), {, }, ` \\m (magic) \\m Default Vim — ., *, ^, $, [ khusus; tapi +, (, { wajib di-escape \\M (nomagic) \\M Hampir semua dianggap karakter literal biasa \\V (very nomagic) \\V Semua literal kecuali simbol \\ Rekomendasi: Selalu pakai awalan \\v (very magic) di awal pencarian Vim agar perilakunya mirip regex modern pada umumnya.\n\u0026#34; Mode magic bawaan Vim — wajib escape kurung, tambah, dll /\\(error\\|warning\\)\\+ \u0026#34; Mode very magic (\\v) — bersih dan gampang dibaca seperti PCRE /\\v(error|warning)+ Pencarian di Vim \u0026#34; Cari ke arah depan (very magic) /\\v pola_cari \u0026#34; Cari ke arah belakang ?\\v pola_cari \u0026#34; Lompat ke kecocokan berikutnya n \u0026#34; Lompat ke kecocokan sebelumnya N \u0026#34; Bersihkan highlight pencarian aktif :noh Sensitivitas Kapital saat Mencari di Vim \u0026#34; Cari tanpa sensitif kapital (ignorecase) /\\cpola /\\cerror \u0026#34; bakal cocok dengan error, Error, ERROR \u0026#34; Cari sensitif kapital /\\Cpola Cari dan Ganti di Vim (Substitute) Sintaks dasar:\n:%s/pola/pengganti/flag Contoh kasus substitute:\n\u0026#34; Ganti semua kata di satu file penuh :%s/fungsiLama/fungsiBaru/g \u0026#34; Ganti disertai konfirmasi satu per satu :%s/namaLama/namaBaru/gc \u0026#34; ketik y = ya, n = lewati, a = ganti semua sisa, q = batalkan \u0026#34; Ganti hanya pada baris visual yang diblok saja :\u0026#39;\u0026lt;,\u0026#39;\u0026gt;s/lama/baru/g \u0026#34; Ganti nama menggunakan very magic (\\v) :%s/\\v(\\w+)\\.length/\\1.size/g \u0026#34; \u0026#34;array.length\u0026#34; menjadi \u0026#34;array.size\u0026#34; \u0026#34; Menghapus spasi di akhir baris :%s/\\s\\+$//e Simbol Pengganti Spesifik di Vim Simbol Arti \\1, \\2 Hasil tangkapan grup 1, 2, dll \\0 atau \u0026amp; Seluruh teks yang cocok \\u Ubah satu karakter berikutnya jadi huruf besar \\l Ubah satu karakter berikutnya jadi huruf kecil \\U Ubah seluruh teks setelahnya jadi huruf besar sampai ketemu \\E \\L Ubah seluruh teks setelahnya jadi huruf kecil sampai ketemu \\E \\E Batas akhir pengubahan huruf \\r Membuat baris baru (newline) pada teks pengganti Contoh penggunaan:\n\u0026#34; Mengubah huruf pertama kata menjadi kapital (Title Case) :%s/\\v\u0026lt;(\\w)/\\u\\1/g \u0026#34; \u0026#34;hello world\u0026#34; → \u0026#34;Hello World\u0026#34; Karakter Khusus Unik Vim Regex Simbol Arti \\\u0026lt; Batas awal kata \\\u0026gt; Batas akhir kata \\zs Penentu awal kecocokan (memotong teks sebelum simbol ini dari output) \\ze Penentu akhir kecocokan \\_s Karakter spasi termasuk baris baru \\{-} Quantifier non-greedy (seperti *? pada PCRE) \u0026#34; Mencocokkan tag HTML secara non-greedy di Vim: /\\v\u0026lt;.{-}\u0026gt; \u0026#34; (Setara dengan \u0026lt;.+?\u0026gt; di PCRE) \u0026#34; Mencocokkan isi argumen di dalam kurung saja /\\v\\(\\zs[^)]+\\ze\\) \u0026#34; Pada \u0026#34;hitung(a, b)\u0026#34; → mencocokkan \u0026#34;a, b\u0026#34; Regex di Terminal (Shell) grep — Mencari di File # Pencarian dasar grep \u0026#34;error\u0026#34; /var/log/syslog # Abaikan huruf kapital grep -i \u0026#34;error\u0026#34; server.log # Gunakan Extended Regex (ERE) — mendukung |, +, () tanpa escape grep -E \u0026#34;(error|warning|critical)\u0026#34; server.log # Tampilkan nomor baris hasil cocok grep -n \u0026#34;TODO\u0026#34; src/*.js # Hanya tampilkan teks yang cocok saja (bukan seluruh baris) grep -o \u0026#34;[0-9]\\+\\.[0-9]\\+\u0026#34; package.json # Tampilkan log baris sebelum dan sesudah hasil cocok grep -B 2 -A 2 \u0026#34;error\u0026#34; app.log # 2 baris sebelum (before) dan sesudah (after) Kesalahan Umum \u0026amp; Solusinya 1. Lupa Meng-escape Titik . Salah: 192.168.0.1 → juga bakal cocok dengan \u0026#34;192x168y0z1\u0026#34; Benar: 192\\.168\\.0\\.1 → hanya cocok dengan \u0026#34;192.168.0.1\u0026#34; Karena titik . di regex berarti karakter apa saja. Selalu escape titik jika ingin mendeteksi karakter titik literal.\n2. Terjebak Masalah Greedy (Rakus) Salah: \u0026lt;.+\u0026gt; Teks: \u0026lt;b\u0026gt;Tebal\u0026lt;/b\u0026gt; Cocok: \u0026lt;b\u0026gt;Tebal\u0026lt;/b\u0026gt; ← memakan seluruh baris tag Benar: \u0026lt;.+?\u0026gt; ← bersifat lazy (malas), memisahkan \u0026lt;b\u0026gt; dan \u0026lt;/b\u0026gt; Lebih Oke: \u0026lt;[^\u0026gt;]+\u0026gt; ← kelas karakter negasi, tidak butuh backtracking 3. Tidak Memasang Anchor Saat Validasi Salah: \\d{5} Teks: \u0026#34;KODE POS: 90210-1234\u0026#34; Hasil: Mendeteksi \u0026#34;90210\u0026#34; di dalam string panjang tersebut Benar: ^\\d{5}$ ← memaksa string harus tepat berisi 5 digit saja Tips Performa Regex Hindari Greedy .* jika bisa: Gunakan kelas karakter negasi. Misalnya, mencari teks di dalam kutip dua, gunakan \u0026quot;[^\u0026quot;]*\u0026quot; daripada \u0026quot;.*?\u0026quot;. Ini jauh lebih cepat dan mencegah backtracking berlebih. Compile Pola yang Dipakai Berulang: Pada Python atau JS (constructor), lakukan compile regex sekali di luar perulangan (loop) agar tidak membebani memori compiler berkali-kali. Gunakan Non-Capturing Group (?:...): Jika kamu hanya butuh mengelompokkan pilihan (ATAU) tanpa berniat memakai isi teksnya di kemudian waktu, non-capturing group menghemat penggunaan alokasi memori. Tabel Rangkuman Cepat Sintaks Utama Pola Arti . Karakter apa saja (kecuali baris baru) \\d Digit angka [0-9] \\w Karakter kata (huruf, angka, _) \\s Karakter spasi [abc] Salah satu dari a, b, atau c [^abc] Selain dari a, b, atau c * 0 kali atau lebih + 1 kali atau lebih ? 0 atau 1 kali {n,m} Antara n sampai m kali *? Versi lazy (non-greedy) dari * ^, $ Awal / akhir baris \\b Batas kata (word boundary) (...) Capturing group (?:...) Non-capturing group (?=...) Lookahead positif (?!...) Lookahead negatif Referensi Cepat Pola Umum Target Pola Tanggal (ISO) \\d{4}-\\d{2}-\\d{2} Alamat IPv4 \\d{1,3}\\.\\d{1,3}\\.\\d{1,3}\\.\\d{1,3} Kode Warna Hex #[0-9a-fA-F]{3,6} Baris Kosong ^\\s*$ Spasi di Akhir \\s+$ Tag HTML \u0026lt;[^\u0026gt;]+\u0026gt; Sumber Belajar Lainnya regex101.com — Tester regex interaktif yang memberikan penjelasan detail per karakter pola (mendukung PCRE, JS, Python). regexr.com — Tester visual regex yang juga sangat bagus dan interaktif. Regular-Expressions.info — Situs tutorial dan panduan regex terlengkap di internet. ","permalink":"https://waldy.id/regex/","summary":"\u003cp\u003eRegular Expressions (regex) itu alat pencocokan pola (pattern-matching) yang ada di hampir semua bahasa pemrograman, text editor, dan command-line tool. Regex membantumu mencari, memvalidasi, mengekstrak, dan mengubah teks dengan bahasa pola yang ringkas.\u003c/p\u003e\n\u003cp\u003eCheatsheet ini didesain sebagai referensi harian kamu — tidak cuma berisi daftar sintaks, tapi juga contoh-contoh praktis yang bakal benar-benar kamu pakai saat memparsing log, memvalidasi input, merefaktorkan kode, atau mencari teks di dalam codebase.\u003c/p\u003e\n\u003chr\u003e\n\u003ch2 id=\"apa-itu-regex\"\u003eApa itu Regex?\u003c/h2\u003e\n\u003cp\u003eRegular Expression (regex) adalah urutan karakter yang membentuk suatu pola pencarian. Kamu memberikan pola tersebut ke engine regex, dan dia bakal mencarikan teks yang cocok dengan pola itu.\u003c/p\u003e","title":"Cheatsheet Lengkap Regex"},{"content":"Vim dan Neovim itu editor modal. Jadi alih-alih pakai mouse untuk semua hal, kamu bakal mengombinasikan mode, motion, operator, dan text object buat edit teks dengan cepat.\nCheatsheet ini didesain buat kerjaan development sehari-hari — panduan praktis yang bisa kamu bookmark dan buka lagi kapan saja.\nKonsep Utama Perintah Vim biasanya dibangun dengan pola seperti ini:\noperator + motion Contohnya:\ndw \u0026#34; hapus kata (delete word) d$ \u0026#34; hapus sampai akhir baris ciw \u0026#34; ubah kata tempat kursor berada (change inside word) yap \u0026#34; salin satu paragraf (yank around paragraph) Kamu juga bisa menambahkan jumlah (count):\n3w \u0026#34; maju 3 kata d3w \u0026#34; hapus 3 kata 5j \u0026#34; turun 5 baris Mindset paling penting:\nJangan dihafal semuanya sekaligus. Pelajari motion dulu, lalu operator, baru kemudian text object.\nMode Mode Arti Cara Masuk Cara Keluar Normal Navigasi dan jalankan perintah Esc - Insert Ketik teks i, a, o Esc Visual Pilih/blok teks v Esc Visual Line Pilih seluruh baris V Esc Visual Block Pilih kolom/blok vertikal Ctrl-v Esc Command-line Jalankan perintah Ex : Enter / Esc Replace Timpa teks yang ada R Esc Terminal Normal Kontrol buffer terminal Ctrl-\\\\ Ctrl-n - Navigasi Dasar Tombol Aksi h Geser ke kiri j Geser ke bawah k Geser ke atas l Geser ke kanan gj Geser ke bawah berdasarkan baris visual (saat line wrap aktif) gk Geser ke atas berdasarkan baris visual (saat line wrap aktif) Gunakan count:\n10j \u0026#34; turun 10 baris 5l \u0026#34; geser ke kanan 5 karakter Navigasi Kata Tombol Aksi w Lompat ke awal kata berikutnya W Lompat ke awal WORD berikutnya (dipisahkan oleh spasi) e Lompat ke akhir kata berikutnya E Lompat ke akhir WORD berikutnya b Lompat mundur ke awal kata B Lompat mundur ke awal WORD ge Lompat mundur ke akhir kata sebelumnya gE Lompat mundur ke akhir WORD sebelumnya Perbedaan antara word dan WORD:\nhello.world example w menganggap tanda baca (seperti titik) sebagai pemisah kata. W hanya menganggap spasi sebagai pemisah kata. Navigasi Baris Tombol Aksi 0 Lompat ke awal baris (kolom pertama) ^ Lompat ke karakter pertama yang bukan spasi $ Lompat ke akhir baris g_ Lompat ke karakter terakhir yang bukan spasi + Lompat ke awal baris berikutnya yang bukan spasi - Lompat ke awal baris sebelumnya yang bukan spasi gg Lompat ke awal file G Lompat ke akhir file 42G Lompat ke baris nomor 42 :42 Lompat ke baris nomor 42 Navigasi Layar Tombol Aksi Ctrl-d Turun setengah halaman Ctrl-u Naik setengah halaman Ctrl-f Turun satu halaman penuh Ctrl-b Naik satu halaman penuh zt Posisikan baris aktif di paling atas layar zz Posisikan baris aktif di tengah layar zb Posisikan baris aktif di paling bawah layar H Lompat ke baris paling atas layar (High) M Lompat ke baris tengah layar (Middle) L Lompat ke baris paling bawah layar (Low) Pencarian dan Navigasi Hasil Tombol Aksi /teks Cari teks ke arah depan ?teks Cari teks ke arah belakang n Lompat ke hasil pencarian berikutnya N Lompat ke hasil pencarian sebelumnya * Cari kata di bawah kursor ke arah depan # Cari kata di bawah kursor ke arah belakang g* Cari kata parsial di bawah kursor ke arah depan g# Cari kata parsial di bawah kursor ke arah belakang Opsi pencarian yang berguna:\n:set ignorecase \u0026#34; cari tanpa sensitif huruf besar/kecil :set smartcase \u0026#34; jadi sensitif kalau kamu ngetik huruf kapital :set hlsearch \u0026#34; aktifkan highlight hasil pencarian :set nohlsearch \u0026#34; matikan highlight hasil pencarian :noh \u0026#34; hapus highlight pencarian aktif saat ini Pencarian Karakter: f, F, t, T Pencarian karakter ini berguna banget buat navigasi cepat dalam satu baris.\nTombol Aksi f\u0026lt;char\u0026gt; Lompat maju ke karakter yang dituju F\u0026lt;char\u0026gt; Lompat mundur ke karakter yang dituju t\u0026lt;char\u0026gt; Lompat maju sampai sebelum karakter yang dituju (till) T\u0026lt;char\u0026gt; Lompat mundur sampai setelah karakter yang dituju ; Ulangi pencarian f, F, t, atau T sebelumnya , Ulangi pencarian sebelumnya tapi dengan arah berlawanan Contoh baris kode:\nconst user = { name: \u0026#34;Pian\u0026#34;, age: 31 }; Lompat ke { f{ Ini bakal mindahin kursor maju tepat di atas karakter {.\nLompat sebelum { t{ Ini bakal mindahin kursor maju satu karakter sebelum {.\nHapus sampai sebelum { dt{ Sebelum:\nconst user = { name: \u0026#34;Pian\u0026#34;, age: 31 }; Sesudah:\n{ name: \u0026#34;Pian\u0026#34;, age: 31 }; Hapus termasuk { df{ Ini bakal menghapus teks dari posisi kursor sampai karakter {.\nUbah teks di dalam kurung kurawal ci{ Ini bakal menghapus isi di dalam { ... } dan langsung masuk ke mode Insert.\nHapus beserta kurung kurawal da{ Ini bakal menghapus { ... } beserta seluruh isinya.\nOperator Operator adalah aksi yang dijalankan. Biasanya butuh motion atau text object setelahnya.\nOperator Arti d Hapus / potong (delete/cut) c Ubah / hapus lalu masuk ke mode Insert (change) y Salin (yank/copy) v Blok teks secara visual (visual select) \u0026gt; Geser indentasi ke kanan \u0026lt; Geser indentasi ke kiri = Auto-format indentasi gq Format teks (wrap text) gu Ubah ke huruf kecil semua gU Ubah ke huruf besar semua ~ Toggle huruf besar/kecil (lowercase \u0026lt;-\u0026gt; uppercase) Kalau operator diketik dua kali, aksinya bakal diterapkan ke baris aktif saat ini:\nPerintah Aksi dd Hapus satu baris cc Ubah satu baris yy Salin satu baris \u0026gt;\u0026gt; Geser indentasi baris ke kanan \u0026lt;\u0026lt; Geser indentasi baris ke kiri == Auto-format indentasi baris aktif gUU Ubah satu baris jadi huruf besar guu Ubah satu baris jadi huruf kecil Contoh Kombinasi Operator + Motion Perintah Aksi dw Hapus sampai awal kata berikutnya dW Hapus sampai awal WORD berikutnya de Hapus sampai akhir kata aktif db Hapus mundur sampai awal kata d$ Hapus sampai akhir baris d0 Hapus mundur sampai awal baris d^ Hapus mundur sampai karakter pertama yang bukan spasi dgg Hapus dari kursor sampai awal file dG Hapus dari kursor sampai akhir file cw Ubah sampai awal kata berikutnya c$ Ubah sampai akhir baris ciw Ubah kata tempat kursor berada ci\u0026quot; Ubah teks di dalam tanda kutip dua ci' Ubah teks di dalam tanda kutip satu ci( Ubah teks di dalam tanda kurung ci{ Ubah teks di dalam kurung kurawal y$ Salin sampai akhir baris yG Salin dari kursor sampai akhir file gUiw Ubah kata aktif jadi huruf besar guw Ubah kata berikutnya jadi huruf kecil Text Object Text object memungkinkan kamu buat memanipulasi struktur teks yang bermakna.\noperator + i/a + object i berarti inside (di dalam objek saja). a berarti around (termasuk karakter pembungkus atau spasi di sekitarnya). Text Object Arti iw Di dalam kata (inside word) aw Seluruh kata beserta spasinya (around word) is Di dalam kalimat (inside sentence) as Seluruh kalimat (around sentence) ip Di dalam paragraf (inside paragraph) ap Seluruh paragraf (around paragraph) i\u0026quot; Di dalam tanda kutip dua a\u0026quot; Seluruh tanda kutip dua beserta isinya i' Di dalam tanda kutip satu a' Seluruh tanda kutip satu beserta isinya i` Di dalam backticks a` Seluruh backticks beserta isinya i( atau ib Di dalam tanda kurung a( atau ab Seluruh tanda kurung beserta isinya i[ Di dalam kurung siku a[ Seluruh kurung siku beserta isinya i{ or iB Di dalam kurung kurawal a{ or aB Seluruh kurung kurawal beserta isinya it Di dalam tag HTML/XML (inside tag) at Seluruh tag HTML/XML beserta isinya Contoh penggunaan:\nciw \u0026#34; ubah kata tempat kursor berada daw \u0026#34; hapus kata beserta spasinya yi\u0026#34; \u0026#34; salin isi di dalam kutip dua da\u0026#34; \u0026#34; hapus kutip dua beserta seluruh isinya ci{ \u0026#34; ubah isi di dalam kurung kurawal ya( \u0026#34; salin seluruh kurung beserta isinya vit \u0026#34; blok visual isi di dalam tag HTML Contoh kasus:\nconst message = \u0026#34;Hello world\u0026#34;; Jalankan perintah ini saat kursor di dalam kata \u0026ldquo;Hello\u0026rdquo;:\nci\u0026#34; Hasilnya:\nconst message = \u0026#34;|\u0026#34;; Kursor kamu langsung masuk ke mode Insert di dalam tanda kutip.\nShortcut Mode Insert Tombol Aksi i Masuk mode Insert sebelum posisi kursor I Masuk mode Insert di awal baris (karakter non-spasi pertama) a Masuk mode Insert setelah posisi kursor (append) A Masuk mode Insert di akhir baris o Buka baris baru di bawah baris aktif lalu masuk mode Insert O Buka baris baru di atas baris aktif lalu masuk mode Insert s Hapus satu karakter di kursor lalu masuk mode Insert S Hapus seluruh baris lalu masuk mode Insert C Hapus sampai akhir baris lalu masuk mode Insert r\u0026lt;char\u0026gt; Ganti satu karakter di kursor dengan karakter baru R Masuk mode Replace (menimpa teks) Ketika berada di dalam mode Insert:\nKombinasi Aksi Ctrl-h Backspace (hapus satu karakter ke belakang) Ctrl-w Hapus satu kata ke belakang Ctrl-u Hapus sampai awal baris Ctrl-o Jalankan satu perintah mode Normal, lalu otomatis balik ke mode Insert Ctrl-r \u0026lt;register\u0026gt; Tempel/paste isi dari register tertentu Ctrl-n Autocomplete kata berikutnya Ctrl-p Autocomplete kata sebelumnya Contoh penggunaan:\nCtrl-o zz Saat lagi ngetik di mode Insert, perintah ini bakal memposisikan baris aktif ke tengah layar tanpa perlu keluar dari mode Insert.\nMengedit Teks Tombol Aksi x Hapus karakter di bawah kursor X Hapus karakter di belakang kursor s Hapus karakter di kursor lalu masuk mode Insert S Hapus satu baris penuh lalu masuk mode Insert r\u0026lt;char\u0026gt; Timpa satu karakter di kursor J Gabungkan baris aktif dengan baris di bawahnya gJ Gabungkan baris tanpa menambahkan spasi pemisah . Ulangi aksi perubahan terakhir u Undo (batalkan aksi) Ctrl-r Redo (ulangi aksi yang dibatalkan) Contoh penggunaan:\nciwhello\u0026lt;Esc\u0026gt; \u0026#34; ganti kata aktif jadi \u0026#39;hello\u0026#39; A;\u0026lt;Esc\u0026gt; \u0026#34; tambahkan titik koma di akhir baris J \u0026#34; gabungkan baris berikutnya ke baris aktif Copy, Cut, dan Paste Tombol Aksi y Salin (yank) dengan motion yy Salin satu baris aktif Y Salin sampai akhir baris (di kebanyakan konfigurasi; di Vim/Neovim modern defaultnya sama dengan yy kecuali diubah) d Hapus/potong (delete/cut) dengan motion dd Hapus/potong satu baris aktif p Tempel (paste) setelah kursor atau di bawah baris aktif P Tempel (paste) sebelum kursor atau di atas baris aktif gp Tempel teks lalu taruh kursor setelah teks tempelan tersebut gP Tempel teks sebelum kursor lalu taruh kursor setelah teks tempelan tersebut Contoh penggunaan:\nyy \u0026#34; salin baris aktif 3yy \u0026#34; salin 3 baris dd \u0026#34; hapus baris aktif 3dd \u0026#34; hapus 3 baris p \u0026#34; tempel di bawah P \u0026#34; tempel di atas Register Register itu tempat penyimpanan sementara buat teks yang kamu salin atau hapus.\nRegister Arti \u0026quot; Register default (unnamed register) 0 Register hasil salin (yank) terakhir 1-9 Register riwayat penghapusan (delete history) + Clipboard sistem operasi * Clipboard seleksi sistem (di beberapa OS) _ Register lubang hitam (black hole); hapus tanpa menyimpannya ke clipboard % Nama file aktif saat ini . Teks terakhir yang dimasukkan : Perintah command-line terakhir yang dijalankan Cara pakai register:\n\u0026#34;+y \u0026#34; salin teks ke clipboard sistem OS \u0026#34;+p \u0026#34; tempel teks dari clipboard sistem OS \u0026#34;_d \u0026#34; hapus teks tanpa menimpa register default \u0026#34;0p \u0026#34; tempel teks hasil salinan terakhir, bukan hasil hapusan terakhir Contoh praktis:\n\u0026#34;+yy \u0026#34; salin baris aktif ke clipboard komputer kamu \u0026#34;_dd \u0026#34; hapus satu baris tanpa merusak teks yang udah kamu salin sebelumnya \u0026#34;0p \u0026#34; tempel teks yang terakhir kamu salin (bukan teks yang terakhir kamu hapus) Undo dan Redo Tombol Aksi u Undo Ctrl-r Redo U Kembalikan baris aktif ke kondisi awal sebelum kursor pindah :earlier 5m Kembalikan file ke kondisi 5 menit yang lalu :later 5m Majukan file ke kondisi 5 menit setelahnya Aktifkan riwayat undo yang persisten di konfigurasi:\nset undofile Neovim dengan Lua:\nvim.opt.undofile = true Mode Visual Tombol Aksi v Blok teks per karakter V Blok teks per baris Ctrl-v Blok teks secara kolom/vertikal (block-wise) o Pindahkan kursor ke ujung blok seleksi lainnya gv Blok ulang area seleksi visual terakhir y Salin area yang diblok d Hapus area yang diblok c Ubah area yang diblok \u0026gt; Geser indentasi area blok ke kanan \u0026lt; Geser indentasi area blok ke kiri = Auto-format indentasi area blok Contoh penggunaan Visual Block:\nCtrl-v j/j/k/k untuk memblok beberapa baris ke bawah I// \u0026lt;Esc\u0026gt; Ini bakal menambahkan komentar // di awal semua baris yang diblok secara bersamaan.\nMenambahkan sesuatu di akhir baris secara masal:\nCtrl-v blok beberapa baris A; \u0026lt;Esc\u0026gt; Ini bakal menambahkan karakter ; di akhir semua baris yang diblok secara bersamaan.\nIndentasi Tombol Aksi \u0026gt;\u0026gt; Geser indentasi baris aktif ke kanan \u0026lt;\u0026lt; Geser indentasi baris aktif ke kiri \u0026gt;} Geser indentasi sampai paragraf berikutnya \u0026lt;} Kurangi indentasi sampai paragraf berikutnya =} Auto-format indentasi sampai paragraf berikutnya gg=G Auto-format indentasi seluruh file dari atas sampai bawah Di Mode Visual:\n\u0026gt; \u0026#34; geser indentasi seleksi ke kanan \u0026lt; \u0026#34; geser indentasi seleksi ke kiri = \u0026#34; auto-format indentasi seleksi Komentar Code Secara default, Vim gak punya shortcut komentar bawaan yang otomatis paham semua bahasa pemrograman. Berikut cara mengakalinya:\nCara manual bawaan Vim I// \u0026lt;Esc\u0026gt; \u0026#34; tambah // di awal baris aktif Untuk banyak baris sekaligus:\nCtrl-v blok baris yang mau dikomentari I// \u0026lt;Esc\u0026gt; Menggunakan Plugin Kebanyakan pengguna Neovim menggunakan plugin komentar seperti numToStr/Comment.nvim atau sejenisnya.\nShortcut bawaan plugin yang umum:\nPerintah Aksi gcc Pasang/lepas komentar pada baris aktif gc (Mode Visual) Pasang/lepas komentar pada teks yang diblok gc{motion} Pasang/lepas komentar berdasarkan motion Contoh:\ngcc \u0026#34; komentari/uncomment baris aktif saat ini gcip \u0026#34; komentari/uncomment seluruh isi paragraf Cari dan Ganti (Search \u0026amp; Replace) Format dasar penggantian teks:\n:s/teks_lama/teks_baru/ Ini bakal mengganti kecocokan pertama di baris aktif saja.\nGanti semua kecocokan di baris aktif saja:\n:s/teks_lama/teks_baru/g Ganti semua kecocokan di seluruh file:\n:%s/teks_lama/teks_baru/g Ganti dengan konfirmasi satu per satu:\n:%s/teks_lama/teks_baru/gc Ganti hanya pada baris yang diblok saja:\n:\u0026#39;\u0026lt;,\u0026#39;\u0026gt;s/teks_lama/teks_baru/g Flag yang sering digunakan:\nFlag Arti g Ganti semua kecocokan di setiap baris (global) c Minta konfirmasi sebelum mengganti (confirm) i Abaikan sensitivitas huruf kapital (ignore case) I Paksa sensitif huruf kapital (case-sensitive) n Hitung jumlah kecocokan tanpa mengganti teksnya Contoh kasus:\n:%s/console.log/logger.info/g :%s/\\\u0026lt;user\\\u0026gt;/customer/gc :%s/foo/bar/gn Karakter spesial saat mengganti teks:\nSimbol Arti \u0026amp; Seluruh teks yang cocok \\1, \\2 Capture group hasil regex pencarian \\r Membuat baris baru (newline) pada teks pengganti \\= Menggunakan ekspresi evaluasi teks pengganti Contoh pakai capture group:\n:%s/\\(first\\)_\\(name\\)/\\1Name/g Perintah Global (:g) Perintah global menjalankan perintah Ex pada semua baris yang cocok dengan pola pencarian.\n:g/pola/perintah Contoh:\n:g/TODO/p \u0026#34; cetak semua baris yang ada tulisan TODO :g/TODO/d \u0026#34; hapus semua baris yang ada tulisan TODO :g/^$/d \u0026#34; hapus semua baris kosong :g/import/s/foo/bar/g :v/TODO/d \u0026#34; hapus semua baris yang GAK ada tulisan TODO Contoh pola praktis:\n:g/^import/normal A; \u0026#34; tambahkan titik koma di akhir semua baris import :g/console.log/d \u0026#34; hapus semua baris yang berisi console.log :g/TODO/t$ \u0026#34; salin semua baris TODO ke bagian paling bawah file File dan Buffer Perintah Aksi :e file Edit / buka file baru :edit file Edit / buka file baru :w Simpan file (write) :w nama_file Simpan sebagai nama file baru :wa Simpan semua buffer aktif (write all) :q Keluar (quit) :q! Keluar paksa tanpa menyimpan perubahan :wq Simpan perubahan lalu keluar :x Simpan jika ada perubahan, lalu keluar ZZ Simpan jika ada perubahan, lalu keluar (mode Normal) ZQ Keluar tanpa simpan (mode Normal) :r file Baca isi file lain dan masukkan ke baris aktif :r !cmd Jalankan perintah bash lalu masukkan hasilnya ke baris aktif Contoh penggunaan:\n:e src/index.ts :w :q :wq :r package.json :r !date Buffer Buffer adalah file yang sedang terbuka di memori.\nPerintah Aksi :ls or :buffers Tampilkan daftar buffer yang terbuka :bnext or :bn Pindah ke buffer berikutnya :bprevious or :bp Pindah ke buffer sebelumnya :buffer 3 or :b 3 Pindah ke buffer nomor 3 :b nama_file Pindah ke buffer berdasarkan nama filenya :bd Tutup buffer aktif (buffer delete) :bd! Tutup paksa buffer aktif :bufdo command Jalankan perintah ke semua buffer yang terbuka Shortcut mapping yang direkomendasikan di config:\nnnoremap \u0026lt;leader\u0026gt;bn :bnext\u0026lt;CR\u0026gt; nnoremap \u0026lt;leader\u0026gt;bp :bprevious\u0026lt;CR\u0026gt; nnoremap \u0026lt;leader\u0026gt;bd :bd\u0026lt;CR\u0026gt; Di Neovim menggunakan Lua:\nvim.keymap.set(\u0026#34;n\u0026#34;, \u0026#34;\u0026lt;leader\u0026gt;bn\u0026#34;, \u0026#34;:bnext\u0026lt;CR\u0026gt;\u0026#34;) vim.keymap.set(\u0026#34;n\u0026#34;, \u0026#34;\u0026lt;leader\u0026gt;bp\u0026#34;, \u0026#34;:bprevious\u0026lt;CR\u0026gt;\u0026#34;) vim.keymap.set(\u0026#34;n\u0026#34;, \u0026#34;\u0026lt;leader\u0026gt;bd\u0026#34;, \u0026#34;:bd\u0026lt;CR\u0026gt;\u0026#34;) Windows / Splits Window adalah area visual untuk melihat isi buffer.\nPerintah Aksi :split or :sp Bagi layar secara horizontal :vsplit or :vsp Bagi layar secara vertikal Ctrl-w s Bagi layar secara horizontal Ctrl-w v Bagi layar secara vertikal Ctrl-w h Pindah fokus ke split sebelah kiri Ctrl-w j Pindah fokus ke split bagian bawah Ctrl-w k Pindah fokus ke split bagian atas Ctrl-w l Pindah fokus ke split sebelah kanan Ctrl-w w Pindah fokus antar split secara bergantian Ctrl-w q Tutup split yang aktif saat ini Ctrl-w o Tutup split lainnya, sisakan split aktif (only) Ctrl-w = Buat ukuran semua split sama rata Ctrl-w _ Maksimalkan tinggi split aktif `Ctrl-w ` Ctrl-w + Perbesar tinggi split aktif Ctrl-w - Perkecil tinggi split aktif Ctrl-w \u0026gt; Perlebar split aktif Ctrl-w \u0026lt; Persempit split aktif Membuka file langsung di split baru:\n:sp src/index.ts :vsp src/index.ts Tab Di Vim, tab itu kumpulan susunan window, bukan file tab seperti pada IDE modern.\nPerintah Aksi :tabnew Buka tab baru :tabnew file Buka file di tab baru :tabnext or gt Pindah ke tab berikutnya :tabprevious or gT Pindah ke tab sebelumnya :tabclose Tutup tab aktif :tabonly Tutup tab lainnya :tabs Daftar semua tab yang terbuka Mark Mark membantumu menandai posisi penting agar bisa lompat ke sana lagi dengan cepat.\nTombol Aksi ma Tandai posisi saat ini sebagai mark lokal a `a Lompat tepat ke posisi mark a 'a Lompat ke awal baris mark a mA Tandai posisi saat ini sebagai mark global A `A Lompat ke mark global A (bisa antar file) :marks Tampilkan semua daftar mark `. Lompat ke lokasi perubahan terakhir `\\\u0026quot; Lompat ke posisi kursor terakhir saat file ditutup `[ Lompat ke awal teks yang terakhir diubah/disalin `] Lompat ke akhir teks yang terakhir diubah/disalin Contoh penggunaan:\nma \u0026#34; simpan posisi saat ini ke mark a G \u0026#34; lompat ke baris paling bawah file `a \u0026#34; lompat balik ke posisi awal tadi secara presisi Jumps dan List Perubahan (Change List) Tombol Aksi Ctrl-o Lompat mundur di daftar riwayat lompatan (jump list) Ctrl-i Lompat maju di daftar riwayat lompatan :jumps Tampilkan riwayat lompatan g; Lompat mundur ke riwayat perubahan teks sebelumnya g, Lompat maju ke riwayat perubahan teks berikutnya :changes Tampilkan riwayat perubahan teks Berguna banget setelah kamu selesai nyari teks, cari definisi fungsi, atau pindah-pindah file.\nMacro Macro digunakan untuk merekam serangkaian aksi lalu memutarnya kembali secara otomatis.\nTombol Aksi qa Mulai merekam ke register a q Berhenti merekam @a Jalankan macro dari register a @@ Jalankan ulang macro yang terakhir kali dipakai 10@a Jalankan macro a sebanyak 10 kali Contoh kasus: menambahkan titik koma ; di akhir baris berurutan.\nTaruh kursor di baris pertama. Rekam macro: qaA;\u0026lt;Esc\u0026gt;jq Jalankan 10 kali ke baris berikutnya: 10@a Penjelasan langkah perekaman:\nLangkah Arti qa Mulai rekam ke register a A; Masuk ke akhir baris lalu ketik ; \u0026lt;Esc\u0026gt; Kembali ke mode Normal j Pindah ke baris di bawahnya q Berhenti merekam Folds (Melipat Teks) Folds digunakan untuk menyembunyikan/melipat bagian teks biar kode terlihat lebih rapi.\nTombol Aksi za Toggle lipatan (buka/tutup lipatan) zo Buka lipatan (open) zc Tutup lipatan (close) zR Buka seluruh lipatan di file (open all) zM Tutup seluruh lipatan di file (close all) zj Pindah ke lipatan berikutnya zk Pindah ke lipatan sebelumnya Mengatur metode pelipatan (fold method):\n:set foldmethod=indent :set foldmethod=syntax :set foldmethod=marker Contoh metode marker:\n// {{{ Helper Auth function login() {} function logout() {} // }}} Quickfix dan Location List Quickfix berguna untuk melacak error se-project, hasil pencarian grep, atau output compiler.\nPerintah Aksi :copen Buka jendela quickfix list :cclose Tutup jendela quickfix list :cnext or :cn Pindah ke item quickfix berikutnya :cprevious or :cp Pindah ke item quickfix sebelumnya :cfirst Pindah ke item quickfix pertama :clast Pindah ke item quickfix terakhir :colder Tampilkan daftar quickfix yang lebih lama :cnewer Tampilkan daftar quickfix yang lebih baru Location list mirip quickfix tapi bersifat lokal per window:\nPerintah Aksi :lopen Buka location list :lclose Tutup location list :lnext Pindah ke item location list berikutnya :lprevious Pindah ke item location list sebelumnya Mencari di dalam project dengan grep bawaan:\n:grep TODO **/*.ts :copen Kalau pakai ripgrep:\n:set grepprg=rg\\ --vimgrep :grep TODO :copen Mode Diff (Komparasi File) Perintah Aksi vimdiff file1 file2 Buka file langsung dalam mode komparasi :diffsplit file Bandingkan file aktif dengan file lain ]c Lompat ke perbedaan berikutnya [c Lompat ke perbedaan sebelumnya do Ambil perubahan dari split sebelah (diff obtain) dp Terapkan perubahan aktif ke split sebelah (diff put) :diffupdate Refresh tampilan komparasi :diffoff Matikan mode komparasi Pemeriksaan Ejaan (Spell Checking) Perintah Aksi :set spell Aktifkan spell check :set nospell Matikan spell check ]s Lompat ke ejaan salah berikutnya [s Lompat ke ejaan salah sebelumnya z= Tampilkan saran ejaan zg Masukkan kata ke kamus (good word) zw Tandai kata sebagai salah (wrong word) zug Batalkan aksi zg Mengatur bahasa spell check:\n:set spelllang=en_us Formatting Teks / Kode Tombol Aksi = Operator auto-indent == Auto-indent baris aktif gg=G Auto-indent seluruh isi file gq Format bungkus teks sesuai lebar batas kolom gqap Format bungkus teks untuk seluruh paragraf aktif Mengatur lebar batas kolom:\n:set textwidth=80 Format teks yang diblok saja:\nv blok teksnya = Format menggunakan LSP Neovim:\n:lua vim.lsp.buf.format() Rekomendasi mapping di config:\nvim.keymap.set(\u0026#34;n\u0026#34;, \u0026#34;\u0026lt;leader\u0026gt;f\u0026#34;, function() vim.lsp.buf.format({ async = true }) end) Terminal Bawaan Membuka terminal di dalam Vim / Neovim Perintah Aksi :terminal Buka jendela terminal baru :term Buka jendela terminal baru i Masuk ke mode ketik di terminal Ctrl-\\\\ Ctrl-n Keluar dari mode ketik terminal (kembali ke mode Normal) :bd! Tutup paksa buffer terminal Membuka terminal langsung dengan split layar:\n:split | terminal :vsplit | terminal Contoh mapping di Neovim Lua agar keluar terminal lebih gampang dengan Esc:\nvim.keymap.set(\u0026#34;t\u0026#34;, \u0026#34;\u0026lt;Esc\u0026gt;\u0026#34;, [[\u0026lt;C-\\\\\u0026gt;\u0026lt;C-n\u0026gt;]]) Neovim LSP (Language Server Protocol) Neovim sudah punya dukungan LSP bawaan. Walaupun konfigurasinya bisa berbeda-beda tiap user, berikut perintah umum yang sering dipakai.\nAksi Perintah Lua Lompat ke definisi fungsi vim.lsp.buf.definition() Lompat ke deklarasi fungsi vim.lsp.buf.declaration() Lompat ke implementasi vim.lsp.buf.implementation() Lompat ke definisi tipe data vim.lsp.buf.type_definition() Tampilkan dokumentasi hover vim.lsp.buf.hover() Bantuan parameter fungsi vim.lsp.buf.signature_help() Ubah nama variabel se-project vim.lsp.buf.rename() Jalankan Code Action vim.lsp.buf.code_action() Format kode vim.lsp.buf.format() Lihat daftar referensi variabel vim.lsp.buf.references() Mapping tombol yang umum dipakai:\nvim.keymap.set(\u0026#34;n\u0026#34;, \u0026#34;gd\u0026#34;, vim.lsp.buf.definition) vim.keymap.set(\u0026#34;n\u0026#34;, \u0026#34;gD\u0026#34;, vim.lsp.buf.declaration) vim.keymap.set(\u0026#34;n\u0026#34;, \u0026#34;gi\u0026#34;, vim.lsp.buf.implementation) vim.keymap.set(\u0026#34;n\u0026#34;, \u0026#34;gr\u0026#34;, vim.lsp.buf.references) vim.keymap.set(\u0026#34;n\u0026#34;, \u0026#34;K\u0026#34;, vim.lsp.buf.hover) vim.keymap.set(\u0026#34;n\u0026#34;, \u0026#34;\u0026lt;leader\u0026gt;rn\u0026#34;, vim.lsp.buf.rename) vim.keymap.set(\u0026#34;n\u0026#34;, \u0026#34;\u0026lt;leader\u0026gt;ca\u0026#34;, vim.lsp.buf.code_action) vim.keymap.set(\u0026#34;n\u0026#34;, \u0026#34;\u0026lt;leader\u0026gt;f\u0026#34;, function() vim.lsp.buf.format({ async = true }) end) Diagnostics Neovim (Error / Warning) Aksi Perintah Lua Buka jendela diagnostik detail vim.diagnostic.open_float() Lompat ke diagnostik berikutnya vim.diagnostic.goto_next() Lompat ke diagnostik sebelumnya vim.diagnostic.goto_prev() Kirim info diagnostik ke location list vim.diagnostic.setloclist() Mapping tombol yang umum dipakai:\nvim.keymap.set(\u0026#34;n\u0026#34;, \u0026#34;\u0026lt;leader\u0026gt;e\u0026#34;, vim.diagnostic.open_float) vim.keymap.set(\u0026#34;n\u0026#34;, \u0026#34;[d\u0026#34;, vim.diagnostic.goto_prev) vim.keymap.set(\u0026#34;n\u0026#34;, \u0026#34;]d\u0026#34;, vim.diagnostic.goto_next) vim.keymap.set(\u0026#34;n\u0026#34;, \u0026#34;\u0026lt;leader\u0026gt;q\u0026#34;, vim.diagnostic.setloclist) Perintah Ex yang Sering Berguna Perintah Aksi :set number Tampilkan nomor baris :set relativenumber Tampilkan nomor baris relatif :set nonumber Sembunyikan nomor baris :set wrap Aktifkan line wrap (teks otomatis melipat ke baris baru di layar) :set nowrap Matikan line wrap :set list Tampilkan karakter tak terlihat (spasi, tab, newline) :set nolist Sembunyikan karakter tak terlihat :set paste Aktifkan mode tempel teks (berguna untuk Vim jadul agar format rapi) :set nopaste Matikan mode tempel teks :syntax on Aktifkan pewarnaan kode (syntax highlighting) :filetype plugin indent on Aktifkan deteksi jenis file dan aturan indentasinya :checkhealth Jalankan cek kesehatan konfigurasi Neovim :messages Tampilkan pesan log sistem :version Lihat informasi versi Vim/Neovim :h topik Buka bantuan dokumentasi tentang topik tersebut :h key-notation Lihat format tombol konfigurasi di dokumentasi Contoh membuka dokumentasi bantuan:\n:h motion.txt :h text-objects :h registers :h :substitute :h vim.lsp.buf Workflow Praktis Sehari-hari 1. Rename variabel dalam satu file :%s/namaLama/namaBaru/gc Pakai flag c biar kamu bisa memverifikasi perubahannya satu per satu.\n2. Hapus semua log debugging (console.log) :g/console.log/d 3. Salin teks di dalam tanda kutip yi\u0026#34; 4. Ganti semua isi di dalam kurung kurawal ci{ 5. Lompat ke suatu karakter dengan cepat f{ Lompat ke depan tepat pada posisi { di baris yang sama.\nt{ Lompat ke depan tepat satu karakter sebelum {.\n6. Ganti isi argumen sebuah fungsi Contoh baris kode:\nsendEmail(user, subject, body) Taruh kursor di dalam tanda kurung fungsi tersebut, lalu jalankan:\nci( Hasilnya:\nsendEmail(|) Kursor kamu otomatis berada di dalam tanda kurung dan langsung siap mengetik.\n7. Blok teks di dalam tag HTML \u0026lt;div class=\u0026#34;card\u0026#34;\u0026gt; Hello world \u0026lt;/div\u0026gt; Taruh kursor di dalam teks isi tag, lalu ketik:\nvit Setelah terblok, kamu bisa melakukan:\nd \u0026#34; hapus area blok tersebut c \u0026#34; ubah isi area blok tersebut y \u0026#34; salin area blok tersebut 8. Perbaiki indentasi satu file penuh gg=G Untuk Neovim yang sudah terpasang LSP:\n:lua vim.lsp.buf.format() 9. Rekam perubahan berulang menggunakan Macro qaA;\u0026lt;Esc\u0026gt;jq 10@a Ini bakal menambahkan karakter ; di akhir 10 baris ke bawah.\n10. Hapus teks tanpa merusak isi clipboard utama \u0026#34;_dd Ini membuang baris teks ke register lubang hitam (black hole register).\nRencana Latihan 7 Hari Hari 1: Navigasi Dasar Latihan tombol berikut:\nh j k l w b e 0 ^ $ gg G Ctrl-d Ctrl-u Target: Navigasi file tanpa menyentuh tombol panah (arrow keys) atau mouse.\nHari 2: Operator Dasar Latihan kombinasi berikut:\ndw dd cw ciw yy p u Ctrl-r Target: Edit teks menggunakan rumus operator + motion.\nHari 3: Karakter Search Latihan tombol pencarian satu baris:\nf{ t{ f, t) ; , Target: Lompat secara instan di dalam baris kode.\nHari 4: Text Object Latihan manipulasi blok:\nci\u0026#34; ci\u0026#39; ci( ci{ dap yiw Target: Edit kode berdasarkan struktur logisnya, bukan karakter per karakter.\nHari 5: Buffer, Split, dan Pencarian File Latihan manajemen file:\n:e nama_file :ls :bn :bp :vsp Ctrl-w h/j/k/l /teks n N Target: Pindah-pindah file dan mengelola split window dengan lancar.\nHari 6: Cari dan Ganti Teks Latihan pengeditan massal:\n:%s/lama/baru/gc :g/pola_teks/d :noh Target: Beres-beres kode kotor atau refactoring file dengan cepat.\nHari 7: Macro dan Register Latihan otomatisasi aksi:\nqa ... q @a @@ \u0026#34;+y \u0026#34;+p \u0026#34;_d Target: Otomatisasi pekerjaan edit teks yang berulang-ulang.\nTabel Rangkuman Singkat Target Aksi Perintah Simpan :w Keluar :q Simpan dan keluar :wq Keluar tanpa simpan :q! Lompat ke awal kata berikutnya w Lompat mundur ke awal kata sebelumnya b Lompat ke akhir baris $ Lompat ke awal baris 0 Lompat ke karakter pertama bukan spasi ^ Pergi ke bagian paling atas file gg Pergi ke bagian paling bawah file G Cari teks /teks Hasil pencarian berikutnya n Hasil pencarian sebelumnya N Bersihkan highlight pencarian :noh Lompat tepat ke { f{ Lompat sebelum { t{ Hapus satu kata dw Ubah kata cw Ubah kata aktif saat ini ciw Ubah isi di dalam tanda kutip dua ci\u0026quot; Ubah isi di dalam kurung kurawal ci{ Hapus satu baris dd Salin satu baris yy Tempel di bawah p Tempel di atas P Undo u Redo Ctrl-r Blok visual biasa v Blok visual per baris V Blok visual kolom (blok vertikal) Ctrl-v Buka file :e nama_file Lihat daftar buffer :ls Pindah ke buffer berikutnya :bn Pindah ke buffer sebelumnya :bp Layar split vertikal :vsp Layar split horizontal :sp Pindah antar split layar Ctrl-w h/j/k/l Rekam macro ke register a qa Stop rekaman macro q Putar/jalankan macro a @a Ulangi aksi pengeditan terakhir . Catatan Penutup Beberapa perintah yang paling sering memberikan peningkatan produktivitas yang drastis adalah:\nf{ \u0026#34; lompat tepat ke suatu karakter ciw \u0026#34; ubah isi kata tempat kursor berada ci\u0026#34; \u0026#34; ubah isi teks di dalam kutip dua ci{ \u0026#34; ubah isi teks di dalam kurung kurawal . \u0026#34; ulangi aksi pengeditan terakhir :%s \u0026#34; cari dan ganti teks massal :g \u0026#34; jalankan perintah Ex pada baris yang cocok qa/@a \u0026#34; rekam dan putar ulang macro otomatis Kalau kamu masih baru belajar Vim atau Neovim, coba terapkan aturan harian sederhana ini:\nTiap kali kamu reflek mau menggerakkan mouse atau tombol panah keyboard, berhenti sejenak, lalu cari motion Vim apa yang bisa menggantikan aksi tersebut.\n","permalink":"https://waldy.id/vim/","summary":"\u003cp\u003eVim dan Neovim itu editor modal. Jadi alih-alih pakai mouse untuk semua hal, kamu bakal mengombinasikan \u003cstrong\u003emode\u003c/strong\u003e, \u003cstrong\u003emotion\u003c/strong\u003e, \u003cstrong\u003eoperator\u003c/strong\u003e, dan \u003cstrong\u003etext object\u003c/strong\u003e buat edit teks dengan cepat.\u003c/p\u003e\n\u003cp\u003eCheatsheet ini didesain buat kerjaan development sehari-hari — panduan praktis yang bisa kamu bookmark dan buka lagi kapan saja.\u003c/p\u003e\n\u003chr\u003e\n\u003ch2 id=\"konsep-utama\"\u003eKonsep Utama\u003c/h2\u003e\n\u003cp\u003ePerintah Vim biasanya dibangun dengan pola seperti ini:\u003c/p\u003e\n\u003cdiv class=\"highlight\"\u003e\u003cpre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;\"\u003e\u003ccode class=\"language-text\" data-lang=\"text\"\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003eoperator + motion\n\u003c/span\u003e\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\u003c/div\u003e\u003cp\u003eContohnya:\u003c/p\u003e\n\u003cdiv class=\"highlight\"\u003e\u003cpre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;\"\u003e\u003ccode class=\"language-vim\" data-lang=\"vim\"\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#a6e22e\"\u003edw\u003c/span\u003e      \u003cspan style=\"color:#75715e\"\u003e\u0026#34; hapus kata (delete word)\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#a6e22e\"\u003ed\u003c/span\u003e$      \u003cspan style=\"color:#75715e\"\u003e\u0026#34; hapus sampai akhir baris\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#a6e22e\"\u003eciw\u003c/span\u003e     \u003cspan style=\"color:#75715e\"\u003e\u0026#34; ubah kata tempat kursor berada (change inside word)\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#a6e22e\"\u003eyap\u003c/span\u003e     \u003cspan style=\"color:#75715e\"\u003e\u0026#34; salin satu paragraf (yank around paragraph)\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\u003c/div\u003e\u003cp\u003eKamu juga bisa menambahkan jumlah (count):\u003c/p\u003e","title":"Cheatsheet Lengkap Vim / Neovim"},{"content":"Agatha Christie itu bukan sekadar penulis misteri. Dia adalah standar. Hampir semua yang kita kenal soal genre ini punya benang merahnya ke Christie — sadar atau tidak.\nkenapa dia masih relevan sampai sekarang Buku-bukunya ditulis puluhan tahun yang lalu, tapi ketika baca tidak terasa usang sama sekali. Cara dia membangun karakter, menyebar clue yang kelihatannya tidak penting di awal, lalu menariknya semua di satu titik di akhir — itu craft yang susah ditiru bahkan oleh penulis modern sekalipun.\nHercule Poirot dengan \u0026ldquo;little grey cells\u0026rdquo;-nya, Miss Marple yang kelihatan seperti nenek-nenek biasa tapi punya mata tajam — mereka bukan sekadar alat untuk memecahkan kasus. Mereka hidup. Punya kepribadian yang konsisten dan kadang mengejutkan.\nyang paling membekas Yang menurutku membuat Christie beda dari penulis misteri kebanyakan adalah dia tidak hanya fokus pada \u0026ldquo;siapa pelakunya\u0026rdquo;. Dia menggali kenapa manusia bisa sampai di titik itu. Ada lapisan psikologi di balik setiap kasusnya, dan itu yang bikin buku-bukunya tidak basi meski dibaca berkali-kali.\nAnd Then There Were None mungkin salah satu konstruksi cerita paling rapi yang pernah aku baca. Sepuluh orang di pulau terpencil, tidak ada yang bisa dipercaya, dan kamu tidak bisa berhenti baca karena setiap halaman terasa ada yang menghilang.\nKalau baru mau mulai baca Christie, satu saran aku: jangan buru-buru. Jangan skip ke akhir. Nikmati cara dia menyusun cerita pelan-pelan. Itu yang bikin baca karyanya terasa beda.\n","permalink":"https://waldy.id/books/agatha-christie/","summary":"\u003cp\u003eAgatha Christie itu bukan sekadar penulis misteri. Dia adalah standar. Hampir semua yang kita kenal soal genre ini punya benang merahnya ke Christie — sadar atau tidak.\u003c/p\u003e\n\u003ch2 id=\"kenapa-dia-masih-relevan-sampai-sekarang\"\u003ekenapa dia masih relevan sampai sekarang\u003c/h2\u003e\n\u003cp\u003eBuku-bukunya ditulis puluhan tahun yang lalu, tapi ketika baca tidak terasa usang sama sekali. Cara dia membangun karakter, menyebar clue yang kelihatannya tidak penting di awal, lalu menariknya semua di satu titik di akhir — itu craft yang susah ditiru bahkan oleh penulis modern sekalipun.\u003c/p\u003e","title":"Penulis Favoritku: Agatha Christie"},{"content":"Kalau Keigo Higashino dan Agatha Christie adalah yang bikin aku jatuh cinta pada misteri, maka Dee Lestari adalah yang bikin aku sadar bahwa penulis Indonesia bisa nulis sesuatu yang benar-benar gila — dalam arti yang paling positif.\npertama kali ketemu Supernova Aku pertama kali baca Dee lewat Supernova seri pertama: Ksatria, Putri, dan Bintang Jatuh. Dan beneran — itu mindblowing.\nBukan karena ceritanya biasa. Tapi karena cara Dee membangun dunianya itu tidak biasa. Ada lapisan sains di dalamnya, ada filosofi, ada romance, dan semuanya tidak terasa dipaksakan satu sama lain. Aku tidak pernah baca penulis Indonesia yang berani seperti itu sebelumnya.\nYang paling kuingat adalah perasaan setelah selesai baca — seperti habis nonton film yang tidak hanya menghibur tapi juga meninggalkan sesuatu di kepala. Ada yang dipertanyakan, ada sudut pandang baru, ada sesuatu yang menempel lama setelah buku ditutup. Dan itu bukan hal yang gampang dicapai.\ntentang Intelegensi Embun Pagi Jujur, aku termasuk yang kurang merasakan nendangnya di seri terakhir ini.\nMungkin ekspektasiku terlalu tinggi setelah membaca seri-seri sebelumnya. Atau mungkin memang closure-nya tidak semenggetarkan yang aku bayangkan di kepala. Bukan berarti jelek — tapi kalau aku bandingkan dengan perasaan pertama kali baca Ksatria, rasanya berbeda jauh.\nSeri pertama punya energi yang segar, seperti ketemu sesuatu yang benar-benar baru. Seri terakhir terasa lebih seperti menutup pintu yang sudah setengah terbuka lama. Mungkin itu memang wajar untuk sebuah penutup seri panjang, tapi tetap saja ada bagian kecil dari aku yang berharap lebih.\nTapi terlepas dari itu, Dee Lestari tetap ada di daftar penulis yang aku hormati. Dia membuktikan bahwa literatur Indonesia tidak harus kalah dengan penulis internasional, dan itu bukan hal yang kecil.\n","permalink":"https://waldy.id/books/dee-lestari/","summary":"\u003cp\u003eKalau Keigo Higashino dan Agatha Christie adalah yang bikin aku jatuh cinta pada misteri, maka Dee Lestari adalah yang bikin aku sadar bahwa penulis Indonesia bisa nulis sesuatu yang benar-benar \u003cem\u003egila\u003c/em\u003e — dalam arti yang paling positif.\u003c/p\u003e\n\u003ch2 id=\"pertama-kali-ketemu-supernova\"\u003epertama kali ketemu Supernova\u003c/h2\u003e\n\u003cp\u003eAku pertama kali baca Dee lewat Supernova seri pertama: \u003cem\u003eKsatria, Putri, dan Bintang Jatuh\u003c/em\u003e. Dan beneran — itu mindblowing.\u003c/p\u003e\n\u003cp\u003eBukan karena ceritanya biasa. Tapi karena cara Dee membangun dunianya itu tidak biasa. Ada lapisan sains di dalamnya, ada filosofi, ada romance, dan semuanya tidak terasa dipaksakan satu sama lain. Aku tidak pernah baca penulis Indonesia yang berani seperti itu sebelumnya.\u003c/p\u003e","title":"Penulis Favoritku: Dee Lestari"},{"content":"Kalau ditanya siapa penulis favoritku, salah satu nama yang pasti langsung keluar adalah Keigo Higashino. Penulis asal Jepang ini punya cara bercerita yang menurutku beda dari kebanyakan — dia tidak hanya bikin kamu bertanya siapa pelakunya, tapi juga kenapa dan seberapa jauh, dan itu yang bikin susah berhenti baca.\nNamiya General Store — yang bikin hangat tanpa ekspektasi Buku Keigo pertama yang aku baca adalah Toko Kelontong Namiya. Dan ini bukan tipikal misteri yang biasanya aku cari.\nCeritanya soal toko tua yang punya \u0026ldquo;kotak surat\u0026rdquo; unik — siapapun yang nulis surat dan masukin ke sana bakal dapat balasan dari masa lalu. Kedengarannya aneh, dan memang aneh. Tapi eksekusinya luar biasa. Setiap cerita yang terhubung ke toko itu dibangun pelan-pelan sampai kamu tiba-tiba sadar sudah terlalu dalam dan susah keluar.\nYang paling aku suka: tidak ada villain di sini. Tidak ada plot twist yang ngejutin. Yang ada cuma manusia biasa yang lagi cari jawaban atas hidupnya, dan toko tua itu jadi jembatan. Entah kenapa itu lebih powerful dari drama apapun. Heart-felt tanpa berasa dipaksakan.\nDevotion of Suspect X — puzzlenya bikin ketagihan Kalau Namiya adalah soal hati, maka The Devotion of Suspect X adalah soal kepala.\nYang menarik dari buku ini: dari halaman pertama kamu sudah tahu siapa pelakunya. Higashino tidak menyembunyikannya. Yang dia sembunyikan adalah bagaimana cara pelaku menutup semua celah — dan di situlah sensasinya.\nAku merasa seperti sedang bermain teka-teki yang jawabannya sudah ada di depan mata tapi tetap saja tidak ketemu. Setiap kali kupikir sudah paham arahnya, ada lapisan baru yang terkuak. Plot twist-nya bukan soal \u0026ldquo;siapa\u0026rdquo;, tapi soal seberapa dalam seseorang rela berkorban — dan itu jatuhnya lebih mengena.\nKalau belum pernah baca Higashino, dua buku ini menurutku titik awal yang paling bagus. Mau mulai dari yang mana dulu? Tergantung lagi pengen baper atau pengen kerja keras mikir.\n","permalink":"https://waldy.id/books/keigo-higashino/","summary":"\u003cp\u003eKalau ditanya siapa penulis favoritku, salah satu nama yang pasti langsung keluar adalah Keigo Higashino. Penulis asal Jepang ini punya cara bercerita yang menurutku beda dari kebanyakan — dia tidak hanya bikin kamu bertanya siapa pelakunya, tapi juga \u003cem\u003ekenapa\u003c/em\u003e dan \u003cem\u003eseberapa jauh\u003c/em\u003e, dan itu yang bikin susah berhenti baca.\u003c/p\u003e\n\u003ch2 id=\"namiya-general-store--yang-bikin-hangat-tanpa-ekspektasi\"\u003eNamiya General Store — yang bikin hangat tanpa ekspektasi\u003c/h2\u003e\n\u003cp\u003eBuku Keigo pertama yang aku baca adalah \u003cem\u003eToko Kelontong Namiya\u003c/em\u003e. Dan ini bukan tipikal misteri yang biasanya aku cari.\u003c/p\u003e","title":"Penulis Favoritku: Keigo Higashino"},{"content":"Akhir-akhir ini lagi rame istilah \u0026ldquo;vibe coding\u0026rdquo; di media sosial, apalagi Threads (soalnya udah ga make Twitter, hehe). Walaupun sudah banyak disebutkan bahwa coding dengan pakai AI tidak semerta-merta disebut vibe coding, hal ini juga disebutkan oleh bang @ariya di Thread-nya dengan mengambil referensi dari Simon Willison: Not All AI-Assisted Programming is Vibe Coding.\nJadi aku mencoba membuat aplikasi keuangan yang kuberi nama Bukuin (bukuin.id). Awalnya tujuanku adalah untuk penggunaan pribadi agar mempermudah lacak pengeluaran/pendapatan, karena sebelumnya melakukan pencatatan di Obsidian.md dan masih belum membentuk kebiasaanku untuk mencatat.\nSeperti yang dikatakan James Clear di buku Atomic Habits, ada poin menarik di \u0026ldquo;4 Laws of Behavior Change\u0026rdquo;, salah satunya adalah make it easy.\nTech Stack Aplikasi ini dibangun menggunakan Flutter. Walaupun aku tidak terlalu pro dalam menggunakan Flutter, tapi aku memahami dasarnya, dan dengan bantuan AI, proses development jadi lebih accessible.\nGimana Prosesnya Kemudian masuk ke fase development:\nBrainstorming dengan AI — Aku lebih sering pakai model Sonnet dari Anthropic. Mulai menyusun prompt yang tujuannya adalah membuat plan termasuk fitur MVP dari aplikasi ini.\nDesign — Masih brainstorming, tapi aku lanjut dengan prompt untuk design mulai dari color-schema, font, dan UI-nya. Dan seperti kebanyakan orang, awal-awal biasanya direkomendasikan warna ungu.\nEksekusi — Aku minta dia define color, design, dan screens.\nTesting — Suruh nulis test untuk setiap function yang dia buat, terutama fitur-fitur utama.\nValidasi — Validasi hasil dengan cara manual testing, lalu prompt, dan begitulah terus mengulang sampai hasilnya seperti saat ini.\nTotal waktu dari ide sampai rilis pertama: kurang lebih 3 bulan.\n2 bulan untuk development 1 bulan untuk proses masuk ke Play Store—karena ada kebijakan wajib 14 hari testing, ditambah terjadi perubahan di fase testing Ini semua dikerjakan di waktu kosong: Sabtu, Minggu, dan malam hari.\nTantangan Tantangan terbesar adalah aku bikin aplikasi ini sebelum Sonnet 3.6 rilis. Jadi aku gonta-ganti model mulai dari GPT-4, SWE dari Windsurf, Gemini 1.5, dan Sonnet 3.5.\nHasilnya? Masih banyak fitur yang menyebabkan bugs—makanya perlu di-test sebaik mungkin dan divalidasi manual. Bahkan di awal bikin, masih ada linter yang error dan inkonsistensi dari design/color schema.\nVibe coding bukan berarti full autopilot. Human validation tetap krusial, apalagi kalau berganti-ganti model AI yang punya \u0026ldquo;kepribadian\u0026rdquo; coding berbeda-beda.\nKalau penasaran, aplikasinya bisa didownload di Play Store dan webnya di bukuin.id. Jangan lupa di-rating ya!\n","permalink":"https://waldy.id/posts/bukuin-vibe-coding/","summary":"\u003cp\u003eAkhir-akhir ini lagi rame istilah \u0026ldquo;vibe coding\u0026rdquo; di media sosial, apalagi Threads (soalnya udah ga make Twitter, hehe). Walaupun sudah banyak disebutkan bahwa coding dengan pakai AI tidak semerta-merta disebut vibe coding, hal ini juga disebutkan oleh bang \u003ca href=\"https://www.threads.com/@ariya114/post/DHpes5WxFqR\"\u003e@ariya di Thread-nya\u003c/a\u003e dengan mengambil referensi dari Simon Willison: \u003ca href=\"https://simonw.substack.com/p/not-all-ai-assisted-programming-is\"\u003eNot All AI-Assisted Programming is Vibe Coding\u003c/a\u003e.\u003c/p\u003e\n\u003cp\u003eJadi aku mencoba membuat aplikasi keuangan yang kuberi nama \u003cstrong\u003eBukuin\u003c/strong\u003e (\u003ca href=\"https://bukuin.id\"\u003ebukuin.id\u003c/a\u003e). Awalnya tujuanku adalah untuk penggunaan pribadi agar mempermudah lacak pengeluaran/pendapatan, karena sebelumnya melakukan pencatatan di Obsidian.md dan masih belum membentuk kebiasaanku untuk mencatat.\u003c/p\u003e","title":"Membuat Aplikasi Catatan Keuangan (Bukuin) dengan Vibe Coding"},{"content":"Menurut saya, Range adalah buku yang menarik untuk dibaca karena menawarkan sudut pandang berbeda dari kebiasaan umum di masyarakat, yaitu fokus mendalami satu keahlian saja. Buku ini justru menunjukkan bahwa dunia kita tidak didesain untuk hanya fokus pada satu bidang, melainkan menuntut pemahaman multidimensi.\nPenulis menjelaskan bahwa ketika kita hanya fokus pada satu bidang, kita cenderung mempelajari pola yang sama berulang kali. Sebaliknya, dengan memahami berbagai disiplin ilmu, kita bisa mengenali beragam pola yang bahkan sebelumnya tidak pernah terbayangkan. Buku ini juga diperkaya dengan banyak analogi yang relevan dan menggambarkan kondisi nyata, sehingga pesan yang disampaikan terasa lebih jelas dan membumi.\n","permalink":"https://waldy.id/books/range/","summary":"\u003cp\u003eMenurut saya, Range adalah buku yang menarik untuk dibaca karena menawarkan sudut pandang berbeda dari kebiasaan umum di masyarakat, yaitu fokus mendalami satu keahlian saja. Buku ini justru menunjukkan bahwa dunia kita tidak didesain untuk hanya fokus pada satu bidang, melainkan menuntut pemahaman multidimensi.\u003c/p\u003e\n\u003cp\u003ePenulis menjelaskan bahwa ketika kita hanya fokus pada satu bidang, kita cenderung mempelajari pola yang sama berulang kali. Sebaliknya, dengan memahami berbagai disiplin ilmu, kita bisa mengenali beragam pola yang bahkan sebelumnya tidak pernah terbayangkan. Buku ini juga diperkaya dengan banyak analogi yang relevan dan menggambarkan kondisi nyata, sehingga pesan yang disampaikan terasa lebih jelas dan membumi.\u003c/p\u003e","title":"Review buku: Range"},{"content":"Sebagai software developer yang terbiasa dengan JavaScript, kamu mungkin sering mengalami masalah seperti:\nPenulisan kode tidak konsisten Nama variabel berantakan Lupa titik koma (;) Gaya indentasi beda-beda Hal ini wajar karena JavaScript memang fleksibel. Tapi kalau proyekmu sudah mulai besar dan melibatkan banyak developer, konsistensi penulisan kode jadi krusial.\nSolusinya: gunakan ESLint, Prettier, Husky, dan Lint-Staged. Dengan ini, kamu bisa memastikan kode tetap rapi, mudah dibaca, dan konsisten di seluruh tim.\n⚡ QUICK START — Setup Otomatis Kalau kamu cuma mau langsung pakai tanpa baca panjang-panjang, ikuti langkah di bawah ini:\n# 1. Install semua dependency npm install --save-dev eslint@latest @eslint/js@latest prettier husky lint-staged # 2. Buat file konfigurasi ESLint touch eslint.config.js 📄 Isi eslint.config.js:\nimport { defineConfig } from \u0026#34;eslint/config\u0026#34;; import js from \u0026#34;@eslint/js\u0026#34;; export default defineConfig([ { files: [\u0026#34;**/*.js\u0026#34;], plugins: { js }, extends: [\u0026#34;js/recommended\u0026#34;], rules: { \u0026#34;no-unused-vars\u0026#34;: \u0026#34;warn\u0026#34;, \u0026#34;no-undef\u0026#34;: \u0026#34;warn\u0026#34;, }, }, ]); # 3. Buat file konfigurasi Prettier touch .prettierrc 📄 Isi .prettierrc:\n{ \u0026#34;printWidth\u0026#34;: 80, \u0026#34;tabWidth\u0026#34;: 2, \u0026#34;useTabs\u0026#34;: false, \u0026#34;semi\u0026#34;: true, \u0026#34;singleQuote\u0026#34;: true, \u0026#34;trailingComma\u0026#34;: \u0026#34;all\u0026#34; } # 4. Inisialisasi Husky npx husky init # 5. Edit file /.husky/pre-commit npx lint-staged 📄 Tambahkan konfigurasi Lint-Staged di package.json:\n\u0026#34;lint-staged\u0026#34;: { \u0026#34;*.{js,ts}\u0026#34;: [ \u0026#34;prettier --write\u0026#34;, \u0026#34;eslint --cache --fix\u0026#34; ] } ✅ Selesai! Sekarang setiap kamu melakukan git commit, kode akan otomatis:\nDiformat oleh Prettier Diperiksa oleh ESLint Diperbaiki secara otomatis jika bisa 📘 Penjelasan Step-by-Step Kalau kamu ingin memahami setiap bagian lebih dalam, berikut penjelasan manualnya:\n🔍 1. ESLint — Linting Kode Apa itu ESLint? ESLint adalah alat untuk mengecek apakah kode kamu sudah sesuai dengan aturan tertentu (rules). Misalnya: ada variabel yang tidak dipakai, lupa deklarasi, dsb.\n📖 Dokumentasi resmi: https://eslint.org\n📦 Instalasi npm install --save-dev eslint@latest @eslint/js@latest ⚙️ Konfigurasi Buat file eslint.config.js:\ntouch eslint.config.js Isi seperti ini:\nimport { defineConfig } from \u0026#34;eslint/config\u0026#34;; import js from \u0026#34;@eslint/js\u0026#34;; export default defineConfig([ { files: [\u0026#34;**/*.js\u0026#34;], plugins: { js }, extends: [\u0026#34;js/recommended\u0026#34;], rules: { \u0026#34;no-unused-vars\u0026#34;: \u0026#34;warn\u0026#34;, \u0026#34;no-undef\u0026#34;: \u0026#34;warn\u0026#34;, }, }, ]); 📌 Kamu bisa ubah rules sesuai kebutuhan tim/proyekmu.\n▶️ Menjalankan ESLint npx eslint src/ # lint seluruh folder npx eslint file.js # lint file tunggal 🎨 2. Prettier — Format Otomatis Apa itu Prettier? Prettier adalah formatter otomatis yang mengatur gaya penulisan kode: indentasi, titik koma, kutip, dsb.\n📖 Dokumentasi resmi: https://prettier.io\n📦 Instalasi npm install --save-dev prettier ⚙️ Konfigurasi Buat file .prettierrc:\ntouch .prettierrc Isi seperti ini:\n{ \u0026#34;printWidth\u0026#34;: 80, \u0026#34;tabWidth\u0026#34;: 2, \u0026#34;useTabs\u0026#34;: false, \u0026#34;semi\u0026#34;: true, \u0026#34;singleQuote\u0026#34;: true, \u0026#34;trailingComma\u0026#34;: \u0026#34;all\u0026#34; } 📌 Ini adalah konfigurasi umum yang banyak dipakai di proyek TypeScript/Node.js modern.\n🪝 3. Husky + Lint-Staged — Hook Git Otomatis Agar proses linting \u0026amp; formatting dijalankan sebelum commit, kita bisa pakai Husky dan Lint-Staged.\n📦 Instalasi npm install --save-dev husky lint-staged npx husky init Ini akan membuat folder .husky/ dan file .husky/pre-commit.\n⚙️ Konfigurasi pre-commit Edit file .husky/pre-commit dan tambahkan:\nnpx lint-staged 🧩 Konfigurasi Lint-Staged Tambahkan di package.json:\n\u0026#34;lint-staged\u0026#34;: { \u0026#34;*.{js,ts}\u0026#34;: [ \u0026#34;prettier --write\u0026#34;, \u0026#34;eslint --cache --fix\u0026#34; ] } Dengan ini:\nFile .js \u0026amp; .ts yang di-stage akan diformat \u0026amp; diperiksa sebelum commit. Commit akan gagal otomatis jika ada error yang tidak bisa diperbaiki otomatis. ✅ Kesimpulan / Highlight ✅ ESLint: memastikan kode sesuai aturan, mendeteksi error lebih awal. ✅ Prettier: membuat kode lebih rapi, konsisten, dan enak dibaca. ✅ Husky + Lint-Staged: memastikan semua kode diformat \u0026amp; di-lint otomatis sebelum commit. 🔥 Dengan setup ini, kamu bisa menjaga kualitas kode tetap tinggi, review PR jadi lebih mudah, dan developer baru lebih cepat adaptasi gaya coding tim.\n🧠 Tips Tambahan Kalau kamu pakai TypeScript, kamu bisa install plugin tambahan seperti @typescript-eslint/eslint-plugin dan @typescript-eslint/parser. Untuk proyek besar, kamu juga bisa tambahkan eslint-config-airbnb atau eslint-config-standard untuk gaya linting yang lebih ketat. ","permalink":"https://waldy.id/posts/eslint-nodejs/","summary":"\u003cp\u003eSebagai software developer yang terbiasa dengan JavaScript, kamu mungkin sering mengalami masalah seperti:\u003c/p\u003e\n\u003cul\u003e\n\u003cli\u003ePenulisan kode tidak konsisten\u003c/li\u003e\n\u003cli\u003eNama variabel berantakan\u003c/li\u003e\n\u003cli\u003eLupa titik koma (\u003ccode\u003e;\u003c/code\u003e)\u003c/li\u003e\n\u003cli\u003eGaya indentasi beda-beda\u003c/li\u003e\n\u003c/ul\u003e\n\u003cp\u003eHal ini wajar karena JavaScript memang fleksibel. Tapi kalau proyekmu sudah mulai \u003cstrong\u003ebesar\u003c/strong\u003e dan melibatkan banyak developer, \u003cstrong\u003ekonsistensi penulisan kode jadi krusial\u003c/strong\u003e.\u003c/p\u003e\n\u003cp\u003eSolusinya: gunakan \u003cstrong\u003eESLint\u003c/strong\u003e, \u003cstrong\u003ePrettier\u003c/strong\u003e, \u003cstrong\u003eHusky\u003c/strong\u003e, dan \u003cstrong\u003eLint-Staged\u003c/strong\u003e.\nDengan ini, kamu bisa memastikan kode tetap rapi, mudah dibaca, dan konsisten di seluruh tim.\u003c/p\u003e","title":"Code Node.js Berantakan? Ini Cara Biar Rapi Pakai ESLint + Prettier di TypeScript / Express"},{"content":"Bagi front-end developer mungkin sudah tidak asing lagi dengan preprocessor css yang akan aku bahasa kali ini yaitu sass. tapi untuk yang belum familiar bisa lihat sendiri didokumentasi Sass. Jadi singkatnya kalian bisa menulis syntax css dengan fitur tambahan yang disediakan oleh sass, serperti nested, variables, modules, dan sebagainya. Namun yang namanya ketergantungan akan membuatmu candu, mau dilepaskan susah mau diteruskan gelisah.\nNote: ini pengalamaan pribadi ya, bisa jadi tidak semua developer relate dengan masalah yang ku alami\u0026hellip;\nAwal Mula Ngicipin Pada awal aku bikin project aplikasi front-end berbasis javascript yang menggunakan sass rasanya sangat nyaman cepat apalagi banyak front-end framework menawarkan penggunaan sass pada saat setup projectnya seperti vuejs dan reactjs, Lalu mulailah terlena menggunakan syntax-syntax dari sass itu sendiri.\nMasalah LibSass Setelah cukup lama menggunakan sass pasti kalian akan menemukan bahwa sass dibangun dengan libSass sebagai core nya, yang mana LibSass itu ditulis dengan c/c++. Jadi ketika kalian menginstall node-sass maka dibackground npm akan memanggil node-gyp untuk compile libSass dan siap digunakan di Nodej.js. Nah sampai disini mulailah masalah-masalah akan muncul kedepannya.\nKarenanode-gyp itu menggunakan python untuk mengcompile native addons. jadi ketika build libSass menggunakan node-gyp ada kemungkinan akan memunculkan error apa bila environment pythonnya itu sendiri berbeda, seperti distutils module yang dihapus mulai dari python3.12 dan setelahnya.\nJadi apabila kalian menemukan error pada saat install node-sass kalian bisa coba cek python version kalian python --version apabila \u0026gt;= 3.12.x maka kalian harus menurunkannya kalau aku sendiri pakai python 3.9.6. setelah menginstall python versi yang lebih rendah lalu tambahkan export PYTHON=/path/to/python3.9.6 di ~/.bashrc atau ~/.zshrc lalu update source terminalnya source ~/.zshrc atau source ~/.bashrc.\nLibSass Deprecated Masalah selanjutnya yang aku temuin adalah LibSass deprecated, dan sass menyarakan menggantinya dengan dart-sass. lihat selengkapnya di LibSass.\ndart-sass di NPM deprecated ketika kalian mencari dart-sass di NPM kalian akan menemukan kalau library ini juga deprecated Dart-Sass. Dan ini cukup membuat bingung developer yang sebenarnya dart-sass itu sendiri sebagai core tidak deprecated namun package dart-sass di npm lah yang deprecated dan direname menjadi sass.\nnpm install sass setelah cukup dibingunkan dengan libSass dan dart-sass aku mencoba install npm install sass. Lalu kemudian terjadilah kekacauan di projectku, karena syntax sass yang baru ternyata banyak yang tidak backward-compatible. dan akupun dilema apa harus dilanjutkan pakai yang deprecated LibSass atau upgrade ke sass? namun codebase yang sudah banyak pastinya diperlukan waktu yang lama untuk refactoring dan memperbaiki syntax sass yang ada.\nKesimpulan Menjadi ketergantungan terhadap dependencies itu memang tidak selamanya nikmat. Jadi menurutku ada sebaiknya untuk kedepannya mengurangi dependencies yang tidak perlu khususnya preprocessor css. karena CSS itu sendiri sudah cukup stabil dan konsisten untuk pengembangan syntaxnya.\n","permalink":"https://waldy.id/posts/ketergantungan-sass/","summary":"\u003cp\u003eBagi front-end developer mungkin sudah tidak asing lagi dengan preprocessor css yang akan aku bahasa kali ini yaitu \u003ccode\u003esass\u003c/code\u003e.\ntapi untuk yang belum familiar bisa lihat sendiri didokumentasi \u003ca href=\"https://sass-lang.com/\"\u003eSass\u003c/a\u003e. Jadi singkatnya kalian bisa menulis syntax css dengan fitur tambahan yang disediakan oleh \u003ccode\u003esass\u003c/code\u003e, serperti nested, variables, modules, dan sebagainya. Namun yang namanya ketergantungan akan membuatmu candu, mau dilepaskan susah mau diteruskan gelisah.\u003c/p\u003e\n\u003cp\u003eNote: ini pengalamaan pribadi ya, bisa jadi tidak semua developer relate dengan masalah yang ku alami\u0026hellip;\u003c/p\u003e","title":"Ketergantungan Preprocessor CSS `Sass` itu bikin mumet kemudian."},{"content":"Disclaimer sebelumnya disclaimer dulu, disini tidak ada ajakan untuk melakukan unsubscribe terhadap medium.com. ini merupakan murni pengalaman dan pendapat pribadi, bukan ajakan.\nAwal Berlangganan sebenarnya aku subscribe medium.com karena akhir-akhir ini sering melakukan research di internet untuk menemukan artikel yang bermanfaat baik itu mengenai teknologi, psikologi ataupun cerita dari orang-orang.\nnamun, dikarekan sering berselancar di internet, kemudian sering ketemu dengan artikel yang berasal dari medium.com, tau sendiri kalau buka artikel yang ada label member-only akan sering muncul popup untuk subscribe, dan begitulah kejadiannya aku subrek ini medium.\nnamun setelah membership sekitar 2 tahun berikut beberapa pengalaman yang membuat aku berhenti berlangganan medium.\nKonten Tidak Terlalu Banyak yang Bermanfaat\nAku akui memang ada konten dari Medium yang menarik dan bermanfaat. Namun, setelah beberapa waktu, aku merasa jumlah konten yang benar-benar berkualitas dan sesuai dengan kebutuhan risetku tidak sebanyak yang diharapkan. Banyak artikel yang terkesan repetitif atau tidak memiliki depth yang cukup untuk memenuhi ekspektasiku.\nHarga Terlalu Mahal Harga langganan medium pada saat tulisan ini dibuat yaitu $60 USD/year, yang menurutku itu relatif mahal, terutama jika dibandingkan dengan jumlah konten yang aku anggap bermanfaat. Dengan biaya yang dikeluarkan, aku merasa tidak mendapatkan return on investment yang sesuai. Banyak platform lain yang menawarkan konten berkualitas dengan harga yang lebih bersaing atau bahkan gratis.\nOke sampai dengan poin pertama dan kedua aku masih bertahan dengan subrek ini medium. namun setelah mereka nge-post ini https://blog.medium.com/medium-stands-for-lgbtqia-rights-ee4d63e8052e langsung aku putuskan tidak melanjutkan berlangganan karena bagiku mengekspose orientasi yang menyimpang bahkan mengkampanyekannya secara berlebihan itu menggelikan.\nTerakhir\u0026hellip; semua itu balik lagi kekebutuhan masing-masing menurutku medium sudah tidak lagi dapat memenuhi keinginan dan ekspektasiku.\n","permalink":"https://waldy.id/posts/unsubrek-medium/","summary":"\u003ch2 id=\"disclaimer\"\u003eDisclaimer\u003c/h2\u003e\n\u003cp\u003esebelumnya disclaimer dulu, disini tidak ada ajakan untuk melakukan unsubscribe terhadap medium.com.\nini merupakan murni pengalaman dan pendapat pribadi, bukan ajakan.\u003c/p\u003e\n\u003ch2 id=\"awal-berlangganan\"\u003eAwal Berlangganan\u003c/h2\u003e\n\u003cp\u003esebenarnya aku subscribe medium.com karena akhir-akhir ini sering melakukan research di internet untuk menemukan artikel yang bermanfaat baik itu mengenai teknologi, psikologi ataupun cerita dari orang-orang.\u003c/p\u003e\n\u003cp\u003enamun, dikarekan sering berselancar di internet, kemudian sering ketemu dengan artikel yang berasal dari medium.com, tau sendiri kalau buka artikel yang ada label member-only akan sering muncul popup untuk subscribe, dan begitulah kejadiannya aku subrek ini medium.\u003c/p\u003e","title":"Mengapa aku berhenti subscribe medium.com"},{"content":"Halo, aku Sofyan Waldy — seorang software engineer otodidak.\nAku banyak berpikir tapi jarang bicara, makanya aku menulis. Blog ini adalah tempatku membagikan hal-hal yang kupelajari, ide-ide menarik, dan kadang-kadang pemikiranku tentang bagaimana sesuatu bekerja di balik layar.\nAku mulai belajar pemrograman lewat C++, dan pengalaman awal itu membuatku selalu penasaran tentang bagaimana sistem bekerja di tingkat yang lebih rendah (low-level). Saat ini aku lebih banyak bekerja dengan JavaScript dan Node.js, tapi aku juga sangat tertarik dengan Go dan suka mengeksplorasi pemrograman sistem menggunakan C kalau ada kesempatan.\nAku juga sangat menyukai Neovim — aku senang membentuk tool kerja agar sesuai dengan cara berpikirku, dan ada kepuasan tersendiri saat workflow kerja terasa benar-benar personal dan pas buat kita.\nDi luar urusan coding, aku banyak membaca buku, suka olahraga, dan menghabiskan waktu bersama orang-orang terdekat.\nKalau kamu ingin menghubungiku: sofyanwaldy@gmail.com\n","permalink":"https://waldy.id/about/","summary":"\u003cp\u003eHalo, aku Sofyan Waldy — seorang software engineer otodidak.\u003c/p\u003e\n\u003cp\u003eAku banyak berpikir tapi jarang bicara, makanya aku menulis. Blog ini adalah tempatku membagikan hal-hal yang kupelajari, ide-ide menarik, dan kadang-kadang pemikiranku tentang bagaimana sesuatu bekerja di balik layar.\u003c/p\u003e\n\u003cp\u003eAku mulai belajar pemrograman lewat C++, dan pengalaman awal itu membuatku selalu penasaran tentang bagaimana sistem bekerja di tingkat yang lebih rendah (low-level). Saat ini aku lebih banyak bekerja dengan JavaScript dan Node.js, tapi aku juga sangat tertarik dengan Go dan suka mengeksplorasi pemrograman sistem menggunakan C kalau ada kesempatan.\u003c/p\u003e","title":"Tentang Saya"}]