Git Melampaui Dasar: Workflow yang Menghemat Berjam-jam Setiap Minggu
Interactive rebase, cherry-pick, bisect, worktrees, reflog rescue, dan strategi branching yang benar-benar berhasil. Perintah Git yang saya gunakan setiap hari yang kebanyakan developer tidak tahu keberadaannya.
Kebanyakan developer belajar lima perintah Git lalu berhenti di situ. add, commit, push, pull, merge. Mungkin checkout dan branch kalau mereka merasa berani. Itu cukup untuk tahun pertama. Lalu branch kamu punya 47 commit dengan pesan seperti "fix" dan "wip" dan "tolong jalan," kamu tidak sengaja me-reset sesuatu yang seharusnya tidak di-reset, dan kamu menghabiskan 40 menit di Stack Overflow mencoba membatalkan merge yang gagal.
Saya sudah menggunakan Git selama bertahun-tahun. Bukan sesekali — secara intensif. Banyak branch, banyak repo, banyak kolaborator, sepanjang hari, setiap hari. Yang berikut ini adalah perintah dan workflow yang benar-benar saya gunakan. Bukan yang terlihat bagus di tutorial. Yang benar-benar menghemat waktu saya, setiap minggu.
Interactive Rebase: Bersihkan Kekacauanmu Sebelum Ada yang Melihat#
Branch kamu punya dua belas commit. Setengahnya bertuliskan "fix typo." Satu bertuliskan "undo commit sebelumnya." Yang lain bertuliskan "kali ini beneran fix." Kamu akan membuka PR. Tidak ada yang perlu melihat riwayat itu.
Interactive rebase adalah cara kamu menulis ulang riwayat di branch-mu sebelum membagikannya. Ini memungkinkanmu menggabungkan commit, mengubah pesan, mengurutkan ulang, atau menghapusnya sepenuhnya.
Perintah Dasar#
git rebase -i HEAD~5Ini membuka editor yang menampilkan 5 commit terakhirmu, dari yang terlama:
pick a1b2c3d Add user authentication endpoint
pick d4e5f6g Fix typo in auth middleware
pick h7i8j9k Add rate limiting
pick l0m1n2o Fix rate limit bug
pick p3q4r5s Update auth testsSetiap baris dimulai dengan perintah. Ubah pick menjadi salah satu dari ini:
squash(ataus) — Gabungkan commit ini ke commit di atasnya, gabungkan pesannyafixup(atauf) — Sama seperti squash, tapi buang pesan commit inireword(ataur) — Pertahankan commit tapi ubah pesannyadrop(ataud) — Hapus commit ini sepenuhnyaedit(ataue) — Jeda rebase di commit ini supaya kamu bisa mengubahnya
Sesi Pembersihan Nyata#
Ini yang benar-benar saya lakukan. Riwayat berantakan di atas menjadi:
pick a1b2c3d Add user authentication endpoint
fixup d4e5f6g Fix typo in auth middleware
pick h7i8j9k Add rate limiting
fixup l0m1n2o Fix rate limit bug
pick p3q4r5s Update auth testsSimpan dan tutup. Sekarang kamu punya tiga commit bersih alih-alih lima. Perbaikan typo digabungkan ke commit auth. Perbaikan bug rate limit digabungkan ke commit rate limit. Reviewer PR-mu melihat progres yang bersih dan logis.
Mengurutkan Ulang Commit#
Kamu bisa benar-benar mengatur ulang barisnya. Jika commit test seharusnya datang sebelum commit rate limiting, cukup pindahkan barisnya:
pick a1b2c3d Add user authentication endpoint
pick p3q4r5s Update auth tests
pick h7i8j9k Add rate limitingGit akan memutar ulang commit-mu dalam urutan baru ini. Jika ada konflik, Git akan berhenti dan membiarkanmu menyelesaikannya.
Pintasan Autosquash#
Jika kamu tahu sebuah commit adalah perbaikan untuk commit sebelumnya, tandai saat commit:
git commit --fixup=a1b2c3dIni membuat commit dengan pesan fixup! Add user authentication endpoint. Lalu saat rebase:
git rebase -i --autosquash HEAD~5Git secara otomatis mengurutkan ulang commit fixup tepat di bawah targetnya dan menandainya sebagai fixup. Kamu tinggal simpan dan tutup. Tidak perlu edit manual.
Saya menggunakan ini terus-menerus. Ini cara tercepat untuk iterasi di branch sambil menjaga riwayat akhir tetap bersih.
Aturan Emas#
Jangan pernah me-rebase commit yang sudah di-push ke branch bersama. Jika orang lain sudah mendasarkan pekerjaannya pada commit tersebut, menulis ulang riwayat akan menyebabkan masalah nyata. Rebase branch fitur milikmu sebelum merge. Jangan pernah rebase main.
Jika kamu sudah push branch fitur-mu dan perlu rebase:
git push --force-with-leaseFlag --force-with-lease lebih aman daripada --force. Flag ini menolak push jika orang lain telah push ke branch yang sama sejak fetch terakhirmu. Tidak akan mencegah semua masalah, tapi menangkap yang paling umum.
Cherry-Pick: Transfer Commit Secara Bedah#
Cherry-pick mengambil commit spesifik dari satu branch dan menerapkannya ke branch lain. Bukan merge. Bukan rebase. Hanya satu commit, diterapkan dengan bersih.
Kapan Saya Benar-benar Menggunakan Ini#
Skenario paling umum: saya memperbaiki bug di branch fitur, tapi perbaikannya juga perlu masuk ke main atau branch release sekarang juga. Saya tidak ingin merge seluruh branch fitur. Saya hanya ingin satu perbaikan itu.
# Cari hash commit dari perbaikan
git log --oneline feature/user-auth
# a1b2c3d Fix null pointer in session validation
# Pindah ke main dan cherry-pick
git checkout main
git cherry-pick a1b2c3dSelesai. Perbaikan sudah di main sebagai commit baru dengan perubahan yang sama.
Cherry-Pick Tanpa Commit#
Terkadang kamu ingin menerapkan perubahan tapi belum mau commit. Mungkin kamu ingin menggabungkan beberapa cherry-pick menjadi satu commit, atau memodifikasi perubahannya sedikit:
git cherry-pick --no-commit a1b2c3dPerubahan di-stage tapi tidak di-commit. Kamu bisa memodifikasinya, menambahkan perubahan lain, lalu commit saat siap.
Cherry-Pick Rentang#
Perlu beberapa commit berurutan? Gunakan sintaks rentang:
git cherry-pick a1b2c3d..f6g7h8iIni meng-cherry-pick semua setelah a1b2c3d sampai dan termasuk f6g7h8i. Perhatikan bahwa a1b2c3d sendiri tidak termasuk. Jika kamu ingin menyertakannya:
git cherry-pick a1b2c3d^..f6g7h8iMenangani Konflik#
Konflik cherry-pick bekerja seperti konflik merge. Saat terjadi:
# Git akan memberitahu ada konflik
# Perbaiki file yang berkonflik, lalu:
git add .
git cherry-pick --continueAtau jika kamu berubah pikiran:
git cherry-pick --abortSatu hal yang perlu diperhatikan: commit yang di-cherry-pick membuat hash commit baru. Jika kamu nanti merge branch aslinya, Git biasanya cukup pintar menangani duplikasi. Tapi jika kamu cherry-pick secara agresif antara branch yang pada akhirnya akan merge, kamu mungkin melihat konflik tak terduga. Gunakan secara bedah, bukan sebagai strategi merge.
Git Bisect: Pencarian Biner untuk Bug#
Sesuatu rusak. Kamu tahu dua minggu lalu masih berfungsi. Sudah ada 200 commit sejak itu. Yang mana yang merusaknya?
Kamu bisa memeriksa setiap commit secara manual. Atau kamu bisa menggunakan git bisect, yang menggunakan pencarian biner untuk menemukan commit penyebab kerusakan tepat dalam log2(n) langkah. Untuk 200 commit, itu sekitar 7-8 pemeriksaan alih-alih 200.
Cara Manual#
# Mulai bisecting
git bisect start
# Tandai commit saat ini sebagai buruk (bug ada di sini)
git bisect bad
# Tandai commit yang diketahui baik (bug belum ada di sini)
git bisect good v2.1.0Git meng-checkout commit di tengah-tengah antara yang baik dan buruk. Uji. Lalu:
# Jika bug ada di commit ini:
git bisect bad
# Jika bug tidak ada di commit ini:
git bisect goodGit mempersempit rentang setengahnya setiap kali. Setelah 7-8 langkah, Git memberitahumu:
a1b2c3d4e5f6g7h is the first bad commit
commit a1b2c3d4e5f6g7h
Author: Some Developer <dev@example.com>
Date: Tue Feb 18 14:23:01 2026 +0300
Refactor session handling to use async middlewareSekarang kamu tahu persis commit mana yang memperkenalkan bug. Saat sudah selesai:
git bisect resetIni mengembalikanmu ke tempat awal.
Cara Otomatis (Ini Kekuatan Sesungguhnya)#
Jika kamu punya test yang bisa mendeteksi bug, kamu bisa mengotomatiskan seluruh prosesnya:
git bisect start
git bisect bad HEAD
git bisect good v2.1.0
git bisect run npm test -- --grep "session validation"Git akan secara otomatis meng-checkout commit, menjalankan test, dan menandainya sebagai baik atau buruk berdasarkan exit code. Nol berarti baik, non-nol berarti buruk. Tinggalkan, kembali, dan Git memberitahumu commit persisnya.
Kamu bisa menggunakan skrip apa pun:
git bisect run ./test-regression.shDi mana test-regression.sh adalah:
#!/bin/bash
npm run build 2>/dev/null || exit 125 # 125 berarti "lewati commit ini"
npm test -- --grep "session" || exit 1 # 1 berarti "buruk"
exit 0 # 0 berarti "baik"Exit code 125 itu spesial — memberitahu bisect untuk melewatkan commit tersebut (berguna jika commit tidak bisa di-compile). Ini salah satu fitur yang terlihat niche sampai kamu membutuhkannya, dan saat itu terjadi, fitur ini menyelamatkan seluruh sore harimu.
Sesi Bisect Nyata#
Seperti ini tampilannya dalam praktik:
$ git bisect start
$ git bisect bad HEAD
$ git bisect good abc1234
Bisecting: 97 revisions left to test after this (roughly 7 steps)
[def5678...] Commit message here
$ npm test -- --grep "login flow"
# Test gagal
$ git bisect bad
Bisecting: 48 revisions left to test after this (roughly 6 steps)
[ghi9012...] Another commit message
$ npm test -- --grep "login flow"
# Test berhasil
$ git bisect good
Bisecting: 24 revisions left to test after this (roughly 5 steps)
...
# Setelah ~7 iterasi:
abc1234def5678ghi is the first bad commitTujuh langkah untuk menemukan jarum di tumpukan jerami 200 commit.
Git Worktrees: Banyak Branch, Tanpa Stashing#
Ini fitur Git yang paling jarang digunakan. Saya yakin kebanyakan developer tidak tahu fitur ini ada.
Masalahnya: kamu sedang dalam-dalam di branch fitur. File berubah di mana-mana. Lalu seseorang berkata "bisa lihat bug produksi ini sebentar?" Kamu punya tiga pilihan:
- Stash semuanya, pindah branch, perbaiki, pindah kembali, pop stash. Berharap semuanya lancar.
- Commit pekerjaan setengah jadimu dengan pesan "wip". Jelek tapi fungsional.
- Clone repo lagi ke direktori berbeda.
Atau pilihan 4: worktrees.
Apa Itu Worktree#
Worktree adalah direktori kerja kedua (atau ketiga, atau keempat) yang terhubung ke repositori yang sama. Setiap worktree punya branch yang di-checkout sendiri, file kerjanya sendiri, index-nya sendiri. Tapi mereka berbagi data .git yang sama, jadi kamu tidak menduplikasi seluruh repo.
Menambahkan Worktree#
# Kamu di feature/user-auth, sedang asyik kerja
# Perlu memperbaiki bug di main:
git worktree add ../hotfix-session mainIni membuat direktori baru ../hotfix-session dengan main yang di-checkout. Direktori kerjamu saat ini tetap persis seperti sebelumnya. Tidak ada yang di-stash, tidak ada yang di-commit, tidak ada yang terganggu.
cd ../hotfix-session
# Perbaiki bug-nya
git add .
git commit -m "Fix null pointer in session validation"
git push origin main
cd ../my-project
# Lanjutkan kerja di fiturmu seolah tidak terjadi apa-apaMembuat Branch Baru di Worktree#
git worktree add ../hotfix-nav -b hotfix/nav-crash mainIni membuat worktree DAN membuat branch baru hotfix/nav-crash berdasarkan main.
Mengelola Worktrees#
# Daftar semua worktrees
git worktree list
# /home/dev/my-project abc1234 [feature/user-auth]
# /home/dev/hotfix-session def5678 [main]
# Hapus worktree saat sudah selesai
git worktree remove ../hotfix-session
# Jika direktorinya sudah dihapus:
git worktree pruneMengapa Ini Lebih Baik dari Stashing#
Stashing baik untuk perpindahan konteks cepat. Tapi worktrees lebih baik untuk apa pun yang memakan waktu lebih dari lima menit:
- IDE-mu tetap terbuka di branch fitur. Tidak ada reindexing, tidak kehilangan posisi scroll.
- Kamu bisa menjalankan test di kedua direktori secara bersamaan.
- Tidak ada risiko konflik stash atau lupa apa yang kamu stash.
- Kamu bisa menjalankan dev server jangka panjang di satu worktree dan build bersih di worktree lain.
Saya biasanya menjaga dua atau tiga worktree aktif: branch fitur utama, worktree main untuk pemeriksaan cepat, dan terkadang worktree review di mana saya meng-checkout PR orang lain.
Satu Catatan#
Kamu tidak bisa meng-checkout branch yang sama di dua worktree. Ini memang dirancang demikian — mencegahmu membuat perubahan bertentangan pada branch yang sama di dua tempat. Jika kamu mencoba, Git akan menolak.
Reflog: Tombol Undo untuk Segalanya#
Kamu melakukan hard reset dan kehilangan commit. Kamu menghapus branch. Kamu rebase dan semuanya jadi kacau balau. Kamu pikir pekerjaanmu hilang.
Tidak. Git hampir tidak pernah benar-benar menghapus apa pun. Reflog adalah jaring pengamanmu.
Apa Itu Reflog#
Setiap kali HEAD berpindah — setiap commit, checkout, rebase, reset, merge — Git mencatatnya di reflog. Ini adalah log dari semua tempat HEAD-mu pernah berada, secara berurutan.
git reflogOutput:
a1b2c3d (HEAD -> main) HEAD@{0}: reset: moving to HEAD~3
f4e5d6c HEAD@{1}: commit: Add payment processing
b7a8c9d HEAD@{2}: commit: Update user dashboard
e0f1g2h HEAD@{3}: commit: Fix auth token refresh
i3j4k5l HEAD@{4}: checkout: moving from feature/payments to mainSetiap entri punya indeks (HEAD@{0}, HEAD@{1}, dll.) dan deskripsi tentang apa yang terjadi.
Pemulihan Setelah Hard Reset#
Kamu tidak sengaja menjalankan git reset --hard HEAD~3 dan kehilangan tiga commit. Mereka ada di reflog:
# Lihat apa yang hilang
git reflog
# Commit sebelum reset ada di HEAD@{1}
git reset --hard f4e5d6cKetiga commit kembali. Krisis teratasi.
Memulihkan Branch yang Dihapus#
Kamu menghapus branch yang punya pekerjaan belum di-merge:
git branch -D feature/experimental
# Aduh, itu ada dua minggu kerjaCommit-nya masih ada. Temukan:
git reflog | grep "feature/experimental"
# Atau cukup lihat reflog untuk commit terakhir di branch tersebut
# Ketemu. Buat ulang branch di commit tersebut:
git branch feature/experimental a1b2c3dBranch-nya kembali, dengan semua commit-nya.
Pemulihan Setelah Rebase yang Gagal#
Kamu rebase dan semuanya kacau. Konflik di mana-mana, commit salah, kekacauan:
# Reflog menunjukkan di mana kamu berada sebelum rebase
git reflog
# a1b2c3d HEAD@{0}: rebase (finish): ...
# ...
# f4e5d6c HEAD@{5}: rebase (start): checkout main
# b7a8c9d HEAD@{6}: commit: Your last good commit
# Kembali ke sebelum rebase
git reset --hard b7a8c9dKamu kembali ke persis di mana kamu sebelum rebase dimulai. Seolah tidak pernah terjadi.
Jaring Pengaman 30 Hari#
Secara default, Git menyimpan entri reflog selama 30 hari (90 hari untuk commit yang reachable). Setelah itu, mereka bisa di-garbage collect. Jadi kamu punya sebulan untuk menyadari kesalahanmu. Dalam praktik, ini lebih dari cukup.
Kamu bisa memeriksa masa kedaluwarsanya:
git config gc.reflogExpire
# default: 90.days.ago (untuk reachable)
git config gc.reflogExpireUnreachable
# default: 30.days.ago (untuk unreachable)Jika kamu paranoid, tingkatkan:
git config --global gc.reflogExpireUnreachable "180.days.ago"Aturan Pribadi#
Sebelum operasi destruktif apa pun — hard reset, force push, penghapusan branch — saya menjalankan git log --oneline -10 dulu. Saya catat HEAD saat ini secara mental. Butuh dua detik dan sudah menyelamatkan saya lebih dari sekali dari kepanikan yang sebenarnya tidak perlu.
Stash dengan Benar: Bukan Sekadar git stash#
Kebanyakan orang menggunakan stash seperti ini:
git stash
# lakukan sesuatu
git stash popItu berhasil, tapi sama saja dengan melempar semuanya ke kotak berlabel "barang." Saat kamu punya tiga stash, kamu tidak tahu mana yang mana.
Beri Nama Stash-mu#
git stash push -m "WIP: validasi form user auth"Sekarang saat kamu list stash:
git stash list
# stash@{0}: On feature/auth: WIP: validasi form user auth
# stash@{1}: On main: Percobaan perbaikan cepat bug nav
# stash@{2}: On feature/payments: Eksperimen dengan Stripe webhooksKamu bisa melihat persis apa isi setiap stash.
Sertakan File yang Belum Di-track#
Secara default, git stash hanya menyimpan file yang di-track. File baru yang belum kamu add akan tertinggal:
# Stash semuanya, termasuk file baru
git stash push --include-untracked -m "WIP: komponen auth baru"
# Atau bahkan sertakan file yang di-ignore (jarang diperlukan)
git stash push --all -m "Snapshot workspace lengkap"Saya menggunakan --include-untracked hampir setiap kali. Meninggalkan file baru saat berpindah branch menyebabkan kebingungan.
Stashing Parsial#
Ini yang kebanyakan orang tidak tahu. Kamu bisa stash file tertentu:
# Stash hanya file tertentu
git stash push -m "Hanya perubahan auth" src/auth/ src/middleware.tsAtau gunakan mode patch untuk stash hunk tertentu dalam file:
git stash push --patch -m "Parsial: hanya logika validasi"Git akan menelusuri setiap perubahan secara interaktif dan bertanya apakah kamu ingin menyimpannya. y untuk ya, n untuk tidak, s untuk memecah hunk menjadi potongan lebih kecil.
Apply vs Pop#
# Pop: terapkan dan hapus dari daftar stash
git stash pop stash@{2}
# Apply: terapkan tapi tetap di daftar stash
git stash apply stash@{2}Saya menggunakan apply saat saya tidak yakin apakah stash akan diterapkan dengan bersih. Jika ada konflik, stash tetap tersimpan. Dengan pop, jika ada konflik, stash tetap ada di daftar juga (banyak orang tidak tahu ini), tapi saya lebih suka intent eksplisit dari apply.
Melihat Isi Stash#
# Lihat file apa yang berubah di stash
git stash show stash@{0}
# Lihat diff lengkap
git stash show -p stash@{0}Membuat Branch dari Stash#
Jika stash-mu sudah berkembang menjadi sesuatu yang lebih substansial:
git stash branch feature/auth-validation stash@{0}Ini membuat branch baru dari commit di mana kamu awalnya stash, menerapkan stash, dan menghapusnya. Bersih.
Strategi Branching: Mana yang Benar-benar Berhasil#
Ada tiga strategi branching mainstream. Masing-masing punya konteks di mana ia bersinar dan konteks di mana ia menyebabkan masalah.
Gitflow#
Klasik. main, develop, feature/*, release/*, hotfix/*. Dibuat oleh Vincent Driessen pada 2010.
# Branch fitur
git checkout -b feature/user-auth develop
# ... kerja ...
git checkout develop
git merge --no-ff feature/user-auth
# Branch release
git checkout -b release/2.1.0 develop
# ... perbaikan akhir ...
git checkout main
git merge --no-ff release/2.1.0
git tag -a v2.1.0 -m "Release 2.1.0"
git checkout develop
git merge --no-ff release/2.1.0
# Hotfix
git checkout -b hotfix/session-fix main
# ... perbaiki ...
git checkout main
git merge --no-ff hotfix/session-fix
git checkout develop
git merge --no-ff hotfix/session-fixKapan berhasil: Aplikasi mobile, software desktop, apa pun dengan rilis berversi bernama dan beberapa versi didukung secara bersamaan. Jika kamu merilis v2.1 dan v3.0 dan perlu mempatch keduanya, Gitflow menangani itu.
Kapan tidak: Aplikasi web dengan continuous deployment. Jika kamu deploy ke produksi 5 kali sehari, seremoni branch release dan branch develop adalah overhead murni. Kebanyakan tim web yang mengadopsi Gitflow berakhir dengan branch develop yang terus-menerus rusak dan branch release yang tidak ada yang paham.
GitHub Flow#
Sederhana. Kamu punya main. Kamu buat branch fitur. Kamu buka PR. Kamu merge ke main. Kamu deploy main.
git checkout -b feature/user-auth main
# ... kerja ...
git push origin feature/user-auth
# Buka PR, di-review, merge
# main selalu bisa di-deployKapan berhasil: Tim kecil hingga menengah yang mengirim aplikasi web. Continuous deployment. Jika main selalu di-deploy, ini saja sudah cukup. Ini yang digunakan situs ini.
Kapan tidak: Saat kamu perlu memelihara beberapa versi release, atau saat kamu punya siklus QA panjang sebelum deployment. GitHub Flow mengasumsikan main masuk ke produksi dengan cepat.
Trunk-Based Development#
Semua orang commit ke main ("trunk") langsung atau melalui branch sangat berumur pendek (kurang dari sehari). Tidak ada branch fitur jangka panjang.
# Branch berumur pendek (merge hari yang sama)
git checkout -b fix/auth-token main
# ... perubahan kecil, fokus ...
git push origin fix/auth-token
# PR di-review dan merge dalam hitungan jam, bukan hariKapan berhasil: Tim berkinerja tinggi dengan CI/CD yang baik, suite test komprehensif, dan feature flag. Google, Meta, dan kebanyakan perusahaan teknologi besar menggunakan trunk-based development. Ini memaksa perubahan kecil dan inkremental serta menghilangkan neraka merge.
Kapan tidak: Tim tanpa test coverage atau CI yang baik. Jika merge ke trunk berarti men-deploy kode yang belum ditest, kamu akan terus-menerus merusak produksi. Kamu juga perlu feature flag untuk apa pun yang memakan waktu lebih dari sehari:
# Feature flag dalam kode
if (featureFlags.isEnabled('new-checkout-flow')) {
renderNewCheckout();
} else {
renderLegacyCheckout();
}Rekomendasi Saya#
Untuk kebanyakan tim pengembangan web: mulai dengan GitHub Flow. Ini sederhana, berhasil, dan tidak memerlukan tooling di luar apa yang sudah disediakan GitHub/GitLab.
Jika timmu berkembang melebihi 15-20 engineer dan kamu deploy beberapa kali sehari, pertimbangkan trunk-based development dengan feature flag. Investasi di infrastruktur feature flag membayar sendiri dalam berkurangnya konflik merge dan iterasi lebih cepat.
Jika kamu mengirim software berversi (aplikasi mobile, tool CLI, library): Gitflow atau versi yang disederhanakan. Kamu memang membutuhkan branch release itu.
Jangan pilih strategi karena sebuah posting blog bilang itu yang terbaik. Pilih yang sesuai dengan cara kamu benar-benar mengirim produk.
Git Hooks: Otomatiskan Hal yang Selalu Kamu Lupa#
Git hooks adalah skrip yang berjalan otomatis pada titik-titik tertentu dalam workflow Git. Mereka lokal di mesinmu (tidak di-push ke remote), yang berarti kamu perlu cara untuk membagikannya dengan tim.
Hooks yang Benar-benar Penting#
pre-commit — Berjalan sebelum setiap commit. Gunakan untuk linting dan formatting:
#!/bin/bash
# .git/hooks/pre-commit
# Jalankan ESLint hanya pada file yang di-stage
STAGED_FILES=$(git diff --cached --name-only --diff-filter=ACM | grep -E '\.(js|ts|tsx)$')
if [ -n "$STAGED_FILES" ]; then
echo "Menjalankan ESLint pada file yang di-stage..."
npx eslint $STAGED_FILES --quiet
if [ $? -ne 0 ]; then
echo "ESLint gagal. Perbaiki error sebelum commit."
exit 1
fi
fi
# Jalankan Prettier pada file yang di-stage
if [ -n "$STAGED_FILES" ]; then
echo "Menjalankan Prettier..."
npx prettier --check $STAGED_FILES
if [ $? -ne 0 ]; then
echo "Pemeriksaan Prettier gagal. Jalankan 'npx prettier --write' terlebih dahulu."
exit 1
fi
ficommit-msg — Memvalidasi format pesan commit. Sempurna untuk memaksakan conventional commits:
#!/bin/bash
# .git/hooks/commit-msg
COMMIT_MSG=$(cat "$1")
PATTERN="^(feat|fix|docs|style|refactor|test|chore|perf|ci|build|revert)(\(.+\))?: .{1,72}"
if ! echo "$COMMIT_MSG" | grep -qE "$PATTERN"; then
echo "Format pesan commit tidak valid."
echo "Yang diharapkan: type(scope): deskripsi"
echo "Contoh: feat(auth): add session refresh endpoint"
echo ""
echo "Tipe valid: feat, fix, docs, style, refactor, test, chore, perf, ci, build, revert"
exit 1
fipre-push — Berjalan sebelum push. Gunakan untuk test:
#!/bin/bash
# .git/hooks/pre-push
echo "Menjalankan test sebelum push..."
npm test
if [ $? -ne 0 ]; then
echo "Test gagal. Push dibatalkan."
exit 1
fiHusky vs Native Hooks#
Native hooks tinggal di .git/hooks/. Masalahnya: direktori .git tidak di-track oleh Git, jadi kamu tidak bisa membagikan hooks melalui repo. Semua orang harus menyiapkannya secara manual.
Husky menyelesaikan ini. Husky menyimpan konfigurasi hook di repo dan mengatur .git/hooks secara otomatis saat npm install:
npx husky initIni membuat direktori .husky/. Tambahkan hooks sebagai file:
# .husky/pre-commit
npx lint-stagedDikombinasikan dengan lint-staged, kamu mendapatkan pemeriksaan pre-commit yang cepat dan terarah:
{
"lint-staged": {
"*.{js,ts,tsx}": ["eslint --fix", "prettier --write"],
"*.css": ["prettier --write"],
"*.json": ["prettier --write"]
}
}Ini menjalankan ESLint dan Prettier hanya pada file yang benar-benar akan kamu commit. Bukan seluruh codebase. Cepat.
Kapan Melewatkan Hooks#
Terkadang kamu perlu commit tanpa hooks berjalan. Hotfix darurat, commit work-in-progress di branch-mu sendiri:
git commit --no-verify -m "WIP: debugging masalah produksi"Gunakan ini secara hemat. Jika kamu sering melewatkan hooks, hooks-mu mungkin terlalu lambat atau terlalu ketat.
Alias yang Menghemat Waktu#
.gitconfig saya sudah berkembang selama bertahun-tahun. Ini adalah alias yang bertahan — yang benar-benar saya gunakan setiap hari, bukan yang saya tambahkan karena terlihat keren.
Pretty Log#
git log default itu bertele-tele. Ini memberikanmu tampilan bersih, berwarna, berbasis graph:
git config --global alias.lg "log --oneline --graph --all --decorate"Penggunaan:
git lg
# * a1b2c3d (HEAD -> main) Fix session validation
# | * d4e5f6g (feature/payments) Add Stripe integration
# | * h7i8j9k Update payment models
# |/
# * l0m1n2o Merge PR #42
# * p3q4r5s Add user dashboardSaya menjalankan ini 20 kali sehari. Ini cara tercepat untuk memahami kondisi repositorimu.
Undo Commit Terakhir#
Pertahankan perubahannya, hanya undo commit-nya:
git config --global alias.undo "reset HEAD~1 --mixed"Penggunaan:
git undo
# Commit hilang, tapi semua perubahan masih di working directory-muSaya menggunakan ini saat commit terlalu cepat, lupa file, atau ingin menyusun ulang perubahan.
Unstage Semuanya#
git config --global alias.unstage "reset HEAD --"Penggunaan:
git unstage src/auth/session.ts
# File di-unstage tapi perubahan tetap adaDaftar Semua Alias#
Karena kamu akan lupa apa yang sudah kamu atur:
git config --global alias.aliases "config --get-regexp ^alias\\."Alias Lain yang Saya Gunakan#
# Tampilkan apa yang akan kamu commit
git config --global alias.staged "diff --staged"
# Status singkat
git config --global alias.st "status -sb"
# Amend tanpa mengubah pesan
git config --global alias.amend "commit --amend --no-edit"
# Tampilkan commit terakhir
git config --global alias.last "log -1 HEAD --stat"
# Pull dengan rebase alih-alih merge
git config --global alias.up "pull --rebase --autostash"
# Hapus branch yang sudah di-merge ke main
git config --global alias.cleanup "!git branch --merged main | grep -v '^[ *]*main$' | xargs git branch -d"Alias up sangat bagus. pull --rebase menjaga riwayatmu linear alih-alih membuat merge commit untuk setiap pull. --autostash secara otomatis menyimpan dan mengembalikan perubahanmu jika kamu punya file yang kotor. Ini seharusnya menjadi perilaku default pull.
Alias cleanup menghapus branch lokal yang sudah di-merge ke main. Setelah beberapa waktu, kamu mengumpulkan puluhan branch basi. Jalankan ini mingguan.
Perintah yang Saya Gunakan Setiap Hari#
Ini bukan alias atau fitur lanjutan. Hanya perintah yang terus saya jalankan yang banyak developer tampaknya tidak tahu.
Perintah Log Terbaik#
git log --oneline --graph --allIni menampilkan setiap branch, setiap merge, seluruh topologi repo-mu dalam tampilan ringkas. Ini hal pertama yang saya jalankan saat pull perubahan. Ini menjawab "apa yang terjadi di repo ini sekarang?"
Diff Perubahan yang Di-stage#
git diff --stagedIni menampilkan apa yang akan di-commit. Bukan apa yang berubah di working directory-mu — apa yang benar-benar di-stage. Saya selalu menjalankan ini sebelum commit. Selalu. Ini menangkap penyertaan tidak sengaja, statement debug, console.log yang seharusnya tidak ada.
# Lihat perubahan yang belum di-stage
git diff
# Lihat perubahan yang sudah di-stage
git diff --staged
# Lihat keduanya
git diff HEADTampilkan Commit Tertentu#
git show a1b2c3dMenampilkan diff lengkap dari satu commit. Berguna saat meninjau riwayat, memahami apa yang sebenarnya diubah sebuah commit.
# Tampilkan hanya file yang berubah
git show --stat a1b2c3d
# Tampilkan file tertentu pada commit tertentu
git show a1b2c3d:src/auth/session.tsYang terakhir itu sangat berguna. Kamu bisa melihat file apa pun pada titik mana pun dalam riwayat tanpa meng-checkout commit tersebut.
Blame dengan Rentang Baris#
git blame -L 42,60 src/auth/session.tsMenampilkan siapa yang terakhir memodifikasi baris 42-60. Lebih berguna daripada blame seluruh file, yang biasanya terlalu banyak.
# Tampilkan pesan commit juga, bukan hanya hash-nya
git blame -L 42,60 --show-name src/auth/session.ts
# Abaikan perubahan whitespace (sangat berguna)
git blame -w -L 42,60 src/auth/session.ts
# Tampilkan commit sebelum yang di-blame (gali lebih dalam)
git log --follow -p -- src/auth/session.tsFlag -w penting. Tanpanya, blame akan mengatribusikan baris ke siapa pun yang terakhir memformat ulang file, yang jarang orang yang kamu cari.
Cari String di Seluruh Riwayat#
# Cari kapan sebuah fungsi ditambahkan atau dihapus
git log -S "validateSession" --oneline
# Cari kapan pola regex muncul
git log -G "session.*timeout" --oneline-S ("pickaxe") menemukan commit di mana jumlah kemunculan string berubah. -G menemukan commit di mana diff-nya cocok dengan regex. Keduanya powerful untuk arkeologi — mencari tahu kapan sesuatu diperkenalkan atau dihapus.
Tampilkan Apa yang Berubah Antara Dua Titik#
# Apa yang berubah antara dua branch
git diff main..feature/auth
# Apa yang berubah di branch ini sejak menyimpang dari main
git diff main...feature/auth
# Daftar hanya file yang berubah
git diff main...feature/auth --name-only
# Tampilan stat (file + sisipan/penghapusan)
git diff main...feature/auth --statDua titik vs tiga titik itu penting. Dua titik menampilkan perbedaan antara ujung kedua branch. Tiga titik menampilkan apa yang berubah di sisi kanan sejak menyimpang dari sisi kiri. Tiga titik biasanya yang kamu inginkan saat meninjau branch fitur.
Bersihkan File yang Belum Di-track#
# Lihat apa yang akan dihapus (dry run)
git clean -n
# Hapus file yang belum di-track
git clean -f
# Hapus file dan direktori yang belum di-track
git clean -fd
# Hapus file yang belum di-track dan yang di-ignore (opsi nuklir)
git clean -fdxSelalu jalankan dengan -n dulu. git clean -fdx akan menghapus node_modules, .env, artefak build — semua yang tidak di-track oleh Git. Berguna untuk awal yang benar-benar bersih, tapi destruktif.
Pulihkan Satu File dari Branch Lain#
# Dapatkan versi main dari sebuah file tanpa berpindah branch
git restore --source main -- src/config/database.tsAtau dari commit tertentu:
git restore --source a1b2c3d -- src/config/database.tsIni lebih bersih dari sintaks lama git checkout main -- path/to/file, dan tidak mempengaruhi HEAD.
Menyatukan Semuanya: Workflow Nyata#
Seperti ini tampilan hari biasa dengan tool-tool ini:
# Pagi: periksa apa yang terjadi
git lg
git fetch --all
# Mulai sebuah fitur
git checkout -b feature/session-refresh main
# Kerja, commit secara inkremental
git add -p # Stage hunk tertentu, bukan seluruh file
git commit -m "Add token refresh endpoint"
git commit -m "Add refresh token rotation"
git commit -m "Fix: handle expired refresh tokens"
git commit -m "Add integration tests"
# Diinterupsi: perlu memperbaiki bug produksi
git worktree add ../hotfix main
cd ../hotfix
# ... perbaiki, commit, push, PR di-merge ...
cd ../my-project
git worktree remove ../hotfix
# Kembali ke kerja fitur
git commit -m "Fix edge case in token validation"
# Siap untuk PR: bersihkan riwayat
git rebase -i main
# Squash commit perbaikan, reword untuk kejelasan
# Push dan buka PR
git push -u origin feature/session-refresh
# Sesuatu rusak di staging? Cari tahu commit mana:
git bisect start
git bisect bad HEAD
git bisect good main
git bisect run npm test
# Aduh, saya hard-reset yang salah
git reflog
git reset --hard HEAD@{2}Setiap perintah ini memakan hitungan detik. Bersama-sama, mereka menghemat berjam-jam. Bukan jam hipotetis — jam nyata, setiap minggu, yang seharusnya saya habiskan untuk mengurai kekacauan Git, mencari bug secara manual, atau kehilangan pekerjaan karena perpindahan konteks.
Git adalah alat yang menghargai kedalaman. Dasar-dasarnya membuatmu melewati hari. Tapi perintah di posting ini yang membedakan "saya menggunakan Git" dari "Git benar-benar membuat saya lebih cepat." Pelajari secara bertahap. Ambil satu teknik baru minggu ini dan gunakan sampai menjadi memori otot. Lalu ambil yang lain.
Dirimu di masa depan, menatap bug produksi jam 11 malam, akan berterima kasih karena sudah tahu git bisect.