Interactive rebase, cherry-pick, bisect, worktree, reflog kurtarma ve gerçekten işe yarayan dallanma stratejileri. Her gün kullandığım ama çoğu geliştiricinin bilmediği Git komutları.
Çoğu geliştirici beş Git komutu öğrenip orada durur. add, commit, push, pull, merge. Cesur hissediyorlarsa belki checkout ve branch. Bu seni ilk yıl idare ettirir. Sonra dalında "fix", "wip" ve "please work" gibi mesajlarla 47 commit olur, yanlışlıkla sıfırlamaması gereken bir şeyi sıfırlarsın ve ters giden bir merge'i geri almak için 40 dakika Stack Overflow'da geçirirsin.
Git'i yıllardır kullanıyorum. Sıradan bir şekilde değil — yoğun bir şekilde. Birden fazla dal, birden fazla repo, birden fazla katkıcı, tüm gün, her gün. Aşağıdakiler gerçekten kullandığım komutlar ve iş akışları. Bir eğitimde iyi görünenler değil. Bana her hafta gerçek zaman kazandıranlar.
Dalında on iki commit var. Yarısı "fix typo." Biri "undo previous commit" diyor. Bir diğeri "actually fix it this time." PR açmak üzeresin. Kimsenin o geçmişi görmesine gerek yok.
Interactive rebase, dalındaki geçmişi paylaşmadan önce yeniden yazmanı sağlar. Commit'leri birleştirebilir, mesajları yeniden yazabilir, sıralayabilir veya tamamen düşürebilirsin.
git rebase -i HEAD~5Bu, son 5 commit'ini en eskiden en yeniye gösteren bir editör açar:
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 testsHer satır bir komutla başlar. pick'i şunlardan biriyle değiştir:
squash (veya s) — Bu commit'i üsttekiyle birleştir, mesajları birleştirfixup (veya f) — Squash gibi, ama bu commit'in mesajını atreword (veya r) — Commit'i koru ama mesajını değiştirdrop (veya d) — Bu commit'i tamamen siledit (veya e) — Rebase'i bu commit'te duraklat, amend edebilsinİşte gerçekte yaptığım şey. Yukarıdaki dağınık geçmiş şöyle olur:
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 testsKaydet ve kapat. Artık beş yerine üç temiz commit'in var. Typo düzeltmesi auth commit'ine katlanır. Rate limit bug düzeltmesi rate limit commit'ine katlanır. PR reviewer'ın temiz, mantıklı bir ilerleme görür.
Satırları kelimenin tam anlamıyla yeniden düzenleyebilirsin. Test commit'i rate limiting'den önce gelmeli ise, satırı taşı:
pick a1b2c3d Add user authentication endpoint
pick p3q4r5s Update auth tests
pick h7i8j9k Add rate limitingGit commit'lerini bu yeni sırada tekrar oynatır. Çakışma varsa durur ve çözmene izin verir.
Bir commit'in öncekinin düzeltmesi olduğunu commit zamanında biliyorsan, commit'lerken işaretle:
git commit --fixup=a1b2c3dBu, fixup! Add user authentication endpoint mesajlı bir commit oluşturur. Sonra rebase yaptığında:
git rebase -i --autosquash HEAD~5Git otomatik olarak fixup commit'lerini hedeflerinin hemen altına taşır ve fixup olarak işaretler. Sadece kaydet ve kapat. Manuel düzenleme yok.
Bunu sürekli kullanıyorum. Nihai geçmişi temiz tutarken bir dalda iterasyon yapmanın en hızlı yolu.
Paylaşılan bir dala push edilmiş commit'leri asla rebase'leme. Başka insanlar o commit'lerin üzerine iş inşa ettiyse, geçmişi yeniden yazmak gerçek sorunlara yol açar. Kendi feature dallarını birleştirmeden önce rebase'le. main'i asla rebase'leme.
Eğer feature dalını zaten push ettiysen ve rebase gerekiyorsa:
git push --force-with-lease--force-with-lease bayrağı --force'dan daha güvenli. Son fetch'inden beri aynı dala başka biri push ettiyse push'u reddeder.
Cherry-pick, bir daldan belirli bir commit'i alıp başka birine uygular. Merge değil. Rebase değil. Sadece bir commit, temizce uygulanmış.
En yaygın senaryo: feature dalımda bir bug düzelttim, ama düzeltmenin main'e veya bir release dalına hemen gitmesi gerekiyor. Tüm feature dalımı merge etmek istemiyorum. Sadece o tek düzeltmeyi istiyorum.
# Düzeltmenin commit hash'ini bul
git log --oneline feature/user-auth
# a1b2c3d Fix null pointer in session validation
# main'e geçip cherry-pick et
git checkout main
git cherry-pick a1b2c3dTamam. Düzeltme main'de aynı değişikliklerle yeni bir commit olarak var.
Bazen değişiklikleri uygulamak ama henüz commit'lememek istersin:
git cherry-pick --no-commit a1b2c3dDeğişiklikler staged ama commit edilmemiş. Değiştirebilir, daha fazla değişiklik ekleyebilir, hazır olunca commit edebilirsin.
Ardışık birden fazla commit mi gerekiyor? Aralık sözdizimini kullan:
git cherry-pick a1b2c3d..f6g7h8iCherry-pick çakışmaları merge çakışmaları gibi çalışır:
# Git bir çakışma olduğunu söyleyecek
# Çakışan dosyaları düzelt, sonra:
git add .
git cherry-pick --continueVeya vazgeçtiysen:
git cherry-pick --abortBir şey bozuldu. İki hafta önce çalıştığını biliyorsun. O zamandan beri 200 commit var. Hangisi bozdu?
Her commit'i elle kontrol edebilirsin. Ya da git bisect kullanabilirsin, bu tam olarak bozulan commit'i bulmak için ikili arama kullanır. 200 commit için yaklaşık 7-8 kontrol, 200 yerine.
# Bisect'i başlat
git bisect start
# Mevcut commit'i kötü olarak işaretle (bug burada var)
git bisect bad
# Bilinen iyi bir commit'i işaretle (bug burada yoktu)
git bisect good v2.1.0Git iyi ile kötü arasında yarıdaki bir commit'i checkout eder. Test et. Sonra:
# Bug bu commit'te varsa:
git bisect bad
# Bug bu commit'te yoksa:
git bisect goodGit aralığı her seferinde yarıya böler. 7-8 adım sonra şunu söyler:
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 middlewareArtık tam olarak hangi commit'in bug'ı tanıttığını biliyorsun. İşin bittiğinde:
git bisect resetBug'ı tespit edebilen bir testin varsa, her şeyi otomatikleştirebilirsin:
git bisect start
git bisect bad HEAD
git bisect good v2.1.0
git bisect run npm test -- --grep "session validation"Git otomatik olarak commit'leri checkout eder, testi çalıştırır ve çıkış koduna göre iyi veya kötü olarak işaretler. Git away, geri gel, ve sana tam commit'i söyler.
Bu en az kullanılan Git özelliği. Çoğu geliştiricinin varlığından haberi olmadığına eminim.
Problem: bir feature dalında derinlerdesin. Her yerde değişmiş dosyalar var. Sonra biri "şu production bug'ına hızlıca bakabilir misin?" diyor. Üç seçeneğin var:
Ya da seçenek 4: worktree.
Worktree, aynı repository'ye bağlı ikinci (veya üçüncü, veya dördüncü) çalışma dizini. Her worktree'nin kendi checkout edilmiş dalı, kendi çalışma dosyaları, kendi index'i var. Ama aynı .git verisini paylaşırlar, yani tüm repo'yu çoğaltmıyorsun.
# feature/user-auth dalındasın, işin içindesin
# main'de bir bug düzeltmen gerekiyor:
git worktree add ../hotfix-session mainBu, main checkout edilmiş yeni bir ../hotfix-session dizini oluşturur. Mevcut dizinin olduğu gibi kalır. Hiçbir şey stash'lenmez, commit'lenmez, bozulmaz.
cd ../hotfix-session
# Bug'ı düzelt
git add .
git commit -m "Fix null pointer in session validation"
git push origin main
cd ../my-project
# Feature'ın üzerinde hiçbir şey olmamış gibi çalışmaya devam et# Tüm worktree'leri listele
git worktree list
# İşin bittiğinde worktree'yi kaldır
git worktree remove ../hotfix-session
# Dizin zaten silindiyse:
git worktree pruneStash hızlı bağlam değişiklikleri için iyi. Ama worktree'ler beş dakikadan fazla sürecek her şey için daha iyi:
Hard reset yaptın ve commit'leri kaybettin. Bir dalı sildin. Rebase yaptın ve her şey berbat oldu. İşinin gittiğini düşünüyorsun.
Gitmedi. Git neredeyse hiçbir şeyi gerçekten silmez. Reflog güvenlik ağın.
HEAD her hareket ettiğinde — her commit, checkout, rebase, reset, merge — Git bunu reflog'a kaydeder.
git reflogÇıktı:
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 mainYanlışlıkla git reset --hard HEAD~3 çalıştırdın ve üç commit'i kaybettin. Reflog'da duruyorlar:
# Neyi kaybettiğini gör
git reflog
# Reset'ten önceki commit HEAD@{1}
git reset --hard f4e5d6cÜç commit geri geldi. Kriz önlendi.
Merge edilmemiş işi olan bir dalı sildin:
git branch -D feature/experimental
# Hayır, orada iki haftalık iş vardıCommit'ler hâlâ var. Bul:
git reflog | grep "feature/experimental"
# Buldun. Dalı o commit'te yeniden oluştur:
git branch feature/experimental a1b2c3dDal tüm commit'leriyle geri döndü.
Rebase yaptın ve her şey ters gitti:
# Reflog rebase'den önce nerede olduğunu gösterir
git reflog
# b7a8c9d HEAD@{6}: commit: Your last good commit
# Rebase'den öncesine dön
git reset --hard b7a8c9dRebase başlamadan önceki haline döndün. Sanki hiç olmamış gibi.
Çoğu kişi stash'i şöyle kullanır:
git stash
# bir şey yap
git stash popBu çalışır, ama her şeyi "eşyalar" etiketli bir kutuya atmaya eşdeğer.
git stash push -m "WIP: user auth form validation"# Yeni dosyalar dahil her şeyi stash'le
git stash push --include-untracked -m "WIP: new auth components"Belirli dosyaları stash'leyebilirsin:
# Sadece belirli dosyaları stash'le
git stash push -m "Just the auth changes" src/auth/ src/middleware.tsKlasik. main, develop, feature/*, release/*, hotfix/*.
Ne zaman çalışır: Mobil uygulamalar, masaüstü yazılımları, adlandırılmış sürümlü release'leri olan ve aynı anda birden fazla sürümü desteklenen her şey.
Ne zaman çalışmaz: Sürekli deployment'lı web uygulamaları. Günde 5 kez production'a deploy ediyorsan, release dalları ve develop dalları saf yük.
Basit. main'in var. Feature dalları oluşturursun. PR açarsın. main'e merge edersin. main'i deploy edersin.
Ne zaman çalışır: Web uygulamaları gönderen küçük-orta takımlar. Sürekli deployment. main her zaman deploy ediliyorsa, ihtiyacın olan her şey bu.
Herkes doğrudan main'e (trunk) commit eder veya çok kısa ömürlü dallar (bir günden az) üzerinden. Uzun süren feature dalları yok.
Ne zaman çalışır: İyi CI/CD'si, kapsamlı test suite'i ve feature flag'leri olan yüksek performanslı takımlar.
Çoğu web geliştirme takımı için: GitHub Flow ile başla. Basit, çalışıyor.
Takımın 15-20 mühendisi aşarsa ve günde birden fazla deploy ediyorsan, feature flag'lerle trunk-based development'a bak.
Sürümlü yazılım gönderiyorsan (mobil uygulamalar, CLI araçları, kütüphaneler): Gitflow veya basitleştirilmiş versiyonu.
Bir blog yazısı "en iyisi bu" dediği için strateji seçme. Gerçekte nasıl gönderdiğine uyanı seç.
pre-commit — Her commit'ten önce çalışır. Linting ve formatlama için kullan:
#!/bin/bash
# .git/hooks/pre-commit
# ESLint'i sadece staged dosyalarda çalıştır
STAGED_FILES=$(git diff --cached --name-only --diff-filter=ACM | grep -E '\.(js|ts|tsx)$')
if [ -n "$STAGED_FILES" ]; then
echo "Running ESLint on staged files..."
npx eslint $STAGED_FILES --quiet
if [ $? -ne 0 ]; then
echo "ESLint failed. Fix errors before committing."
exit 1
fi
ficommit-msg — Commit mesajı formatını doğrular:
#!/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 "Invalid commit message format."
echo "Expected: type(scope): description"
exit 1
fiHusky hook yapılandırmalarını repo'da saklar ve npm install'da .git/hooks'u otomatik kurar:
npx husky initlint-staged ile birleştirildiğinde hızlı, hedefli pre-commit kontrolleri elde edersin:
{
"lint-staged": {
"*.{js,ts,tsx}": ["eslint --fix", "prettier --write"],
"*.css": ["prettier --write"],
"*.json": ["prettier --write"]
}
}git config --global alias.lg "log --oneline --graph --all --decorate"Bunu günde 20 kez çalıştırıyorum. Repository'nin durumunu anlamanın en hızlı yolu.
git config --global alias.undo "reset HEAD~1 --mixed"# Commit edeceğin şeyi göster
git config --global alias.staged "diff --staged"
# Kısa durum
git config --global alias.st "status -sb"
# Mesajı değiştirmeden amend
git config --global alias.amend "commit --amend --no-edit"
# Merge yerine rebase ile pull
git config --global alias.up "pull --rebase --autostash"
# main'e merge edilmiş dalları sil
git config --global alias.cleanup "!git branch --merged main | grep -v '^[ *]*main$' | xargs git branch -d"up alias'ı özellikle iyi. pull --rebase her pull için merge commit'i oluşturmak yerine geçmişini düz tutar. --autostash kirli dosyaların varsa değişikliklerini otomatik stash'ler ve geri yükler.
git diff --stagedBu commit'lenecek olanı gösterir. Commit'lemeden önce her zaman çalıştırıyorum. Her zaman. Yanlışlıkla dahil etmeleri, debug ifadelerini, olmaması gereken console.log'ları yakalar.
git show a1b2c3dgit blame -L 42,60 src/auth/session.ts42-60 arasındaki satırları kimin en son değiştirdiğini gösterir.
# Bir fonksiyonun ne zaman eklendiğini veya kaldırıldığını bul
git log -S "validateSession" --oneline
# Bir regex kalıbının ne zaman göründüğünü bul
git log -G "session.*timeout" --onelineTipik bir gün bu araçlarla şöyle görünür:
# Sabah: neler oluyor kontrol et
git lg
git fetch --all
# Bir feature başlat
git checkout -b feature/session-refresh main
# Çalış, artımlı commit'le
git add -p # Tüm dosyalar değil, belirli hunk'lar stage et
git commit -m "Add token refresh endpoint"
# Araya girme: production bug düzeltmesi gerekiyor
git worktree add ../hotfix main
cd ../hotfix
# ... düzelt, commit'le, push et, PR merge edildi ...
cd ../my-project
git worktree remove ../hotfix
# PR'a hazır: geçmişi temizle
git rebase -i main
# Push et ve PR aç
git push -u origin feature/session-refresh
# Staging'de bir şey mi bozuldu? Hangi commit bul:
git bisect start
git bisect bad HEAD
git bisect good main
git bisect run npm test
# Yanlış şeyi hard-reset ettim
git reflog
git reset --hard HEAD@{2}Bu komutların her biri saniyeler sürer. Birlikte, saatler kazandırır. Varsayımsal saatler değil — gerçek saatler, her hafta.
Git, derinliği ödüllendiren bir araç. Temel bilgiler günü kurtarır. Ama bu yazıdaki komutlar, "Git kullanıyorum" ile "Git beni gerçekten hızlandırıyor" arasını ayıran şeyler. Artımlı öğren. Bu hafta bir yeni teknik seç ve kas hafızası olana kadar kullan. Sonra bir tane daha seç.
Gece 11'de bir production bug'ına bakan gelecekteki sen, git bisect'i bildiğin için sana teşekkür edecek.