Lompat ke konten
·21 menit membaca

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.

Bagikan:X / TwitterLinkedIn

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#

bash
git rebase -i HEAD~5

Ini membuka editor yang menampilkan 5 commit terakhirmu, dari yang terlama:

bash
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 tests

Setiap baris dimulai dengan perintah. Ubah pick menjadi salah satu dari ini:

  • squash (atau s) — Gabungkan commit ini ke commit di atasnya, gabungkan pesannya
  • fixup (atau f) — Sama seperti squash, tapi buang pesan commit ini
  • reword (atau r) — Pertahankan commit tapi ubah pesannya
  • drop (atau d) — Hapus commit ini sepenuhnya
  • edit (atau e) — Jeda rebase di commit ini supaya kamu bisa mengubahnya

Sesi Pembersihan Nyata#

Ini yang benar-benar saya lakukan. Riwayat berantakan di atas menjadi:

bash
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 tests

Simpan 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:

bash
pick a1b2c3d Add user authentication endpoint
pick p3q4r5s Update auth tests
pick h7i8j9k Add rate limiting

Git 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:

bash
git commit --fixup=a1b2c3d

Ini membuat commit dengan pesan fixup! Add user authentication endpoint. Lalu saat rebase:

bash
git rebase -i --autosquash HEAD~5

Git 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:

bash
git push --force-with-lease

Flag --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.

bash
# 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 a1b2c3d

Selesai. 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:

bash
git cherry-pick --no-commit a1b2c3d

Perubahan 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:

bash
git cherry-pick a1b2c3d..f6g7h8i

Ini meng-cherry-pick semua setelah a1b2c3d sampai dan termasuk f6g7h8i. Perhatikan bahwa a1b2c3d sendiri tidak termasuk. Jika kamu ingin menyertakannya:

bash
git cherry-pick a1b2c3d^..f6g7h8i

Menangani Konflik#

Konflik cherry-pick bekerja seperti konflik merge. Saat terjadi:

bash
# Git akan memberitahu ada konflik
# Perbaiki file yang berkonflik, lalu:
git add .
git cherry-pick --continue

Atau jika kamu berubah pikiran:

bash
git cherry-pick --abort

Satu 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#

bash
# 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.0

Git meng-checkout commit di tengah-tengah antara yang baik dan buruk. Uji. Lalu:

bash
# Jika bug ada di commit ini:
git bisect bad
 
# Jika bug tidak ada di commit ini:
git bisect good

Git mempersempit rentang setengahnya setiap kali. Setelah 7-8 langkah, Git memberitahumu:

bash
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 middleware

Sekarang kamu tahu persis commit mana yang memperkenalkan bug. Saat sudah selesai:

bash
git bisect reset

Ini mengembalikanmu ke tempat awal.

Cara Otomatis (Ini Kekuatan Sesungguhnya)#

Jika kamu punya test yang bisa mendeteksi bug, kamu bisa mengotomatiskan seluruh prosesnya:

bash
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:

bash
git bisect run ./test-regression.sh

Di mana test-regression.sh adalah:

bash
#!/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:

bash
$ 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 commit

Tujuh 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:

  1. Stash semuanya, pindah branch, perbaiki, pindah kembali, pop stash. Berharap semuanya lancar.
  2. Commit pekerjaan setengah jadimu dengan pesan "wip". Jelek tapi fungsional.
  3. 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#

bash
# Kamu di feature/user-auth, sedang asyik kerja
# Perlu memperbaiki bug di main:
 
git worktree add ../hotfix-session main

Ini 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.

bash
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-apa

Membuat Branch Baru di Worktree#

bash
git worktree add ../hotfix-nav -b hotfix/nav-crash main

Ini membuat worktree DAN membuat branch baru hotfix/nav-crash berdasarkan main.

Mengelola Worktrees#

bash
# 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 prune

Mengapa 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.

bash
git reflog

Output:

bash
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 main

Setiap 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:

bash
# Lihat apa yang hilang
git reflog
 
# Commit sebelum reset ada di HEAD@{1}
git reset --hard f4e5d6c

Ketiga commit kembali. Krisis teratasi.

Memulihkan Branch yang Dihapus#

Kamu menghapus branch yang punya pekerjaan belum di-merge:

bash
git branch -D feature/experimental
# Aduh, itu ada dua minggu kerja

Commit-nya masih ada. Temukan:

bash
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 a1b2c3d

Branch-nya kembali, dengan semua commit-nya.

Pemulihan Setelah Rebase yang Gagal#

Kamu rebase dan semuanya kacau. Konflik di mana-mana, commit salah, kekacauan:

bash
# 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 b7a8c9d

Kamu 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:

bash
git config gc.reflogExpire
# default: 90.days.ago (untuk reachable)
git config gc.reflogExpireUnreachable
# default: 30.days.ago (untuk unreachable)

Jika kamu paranoid, tingkatkan:

bash
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:

bash
git stash
# lakukan sesuatu
git stash pop

Itu 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#

bash
git stash push -m "WIP: validasi form user auth"

Sekarang saat kamu list stash:

bash
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 webhooks

Kamu 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:

bash
# 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:

bash
# Stash hanya file tertentu
git stash push -m "Hanya perubahan auth" src/auth/ src/middleware.ts

Atau gunakan mode patch untuk stash hunk tertentu dalam file:

bash
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#

bash
# 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#

bash
# 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:

bash
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.

bash
# 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-fix

Kapan 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.

bash
git checkout -b feature/user-auth main
# ... kerja ...
git push origin feature/user-auth
# Buka PR, di-review, merge
# main selalu bisa di-deploy

Kapan 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.

bash
# 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 hari

Kapan 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:

bash
# 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:

bash
#!/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
fi

commit-msg — Memvalidasi format pesan commit. Sempurna untuk memaksakan conventional commits:

bash
#!/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
fi

pre-push — Berjalan sebelum push. Gunakan untuk test:

bash
#!/bin/bash
# .git/hooks/pre-push
 
echo "Menjalankan test sebelum push..."
npm test
if [ $? -ne 0 ]; then
  echo "Test gagal. Push dibatalkan."
  exit 1
fi

Husky 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:

bash
npx husky init

Ini membuat direktori .husky/. Tambahkan hooks sebagai file:

bash
# .husky/pre-commit
npx lint-staged

Dikombinasikan dengan lint-staged, kamu mendapatkan pemeriksaan pre-commit yang cepat dan terarah:

json
{
  "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:

bash
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:

bash
git config --global alias.lg "log --oneline --graph --all --decorate"

Penggunaan:

bash
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 dashboard

Saya menjalankan ini 20 kali sehari. Ini cara tercepat untuk memahami kondisi repositorimu.

Undo Commit Terakhir#

Pertahankan perubahannya, hanya undo commit-nya:

bash
git config --global alias.undo "reset HEAD~1 --mixed"

Penggunaan:

bash
git undo
# Commit hilang, tapi semua perubahan masih di working directory-mu

Saya menggunakan ini saat commit terlalu cepat, lupa file, atau ingin menyusun ulang perubahan.

Unstage Semuanya#

bash
git config --global alias.unstage "reset HEAD --"

Penggunaan:

bash
git unstage src/auth/session.ts
# File di-unstage tapi perubahan tetap ada

Daftar Semua Alias#

Karena kamu akan lupa apa yang sudah kamu atur:

bash
git config --global alias.aliases "config --get-regexp ^alias\\."

Alias Lain yang Saya Gunakan#

bash
# 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#

bash
git log --oneline --graph --all

Ini 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#

bash
git diff --staged

Ini 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.

bash
# Lihat perubahan yang belum di-stage
git diff
 
# Lihat perubahan yang sudah di-stage
git diff --staged
 
# Lihat keduanya
git diff HEAD

Tampilkan Commit Tertentu#

bash
git show a1b2c3d

Menampilkan diff lengkap dari satu commit. Berguna saat meninjau riwayat, memahami apa yang sebenarnya diubah sebuah commit.

bash
# Tampilkan hanya file yang berubah
git show --stat a1b2c3d
 
# Tampilkan file tertentu pada commit tertentu
git show a1b2c3d:src/auth/session.ts

Yang 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#

bash
git blame -L 42,60 src/auth/session.ts

Menampilkan siapa yang terakhir memodifikasi baris 42-60. Lebih berguna daripada blame seluruh file, yang biasanya terlalu banyak.

bash
# 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.ts

Flag -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#

bash
# 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#

bash
# 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 --stat

Dua 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#

bash
# 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 -fdx

Selalu 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#

bash
# Dapatkan versi main dari sebuah file tanpa berpindah branch
git restore --source main -- src/config/database.ts

Atau dari commit tertentu:

bash
git restore --source a1b2c3d -- src/config/database.ts

Ini 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:

bash
# 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.

Artikel Terkait