İçeriğe geç
·10 dk okuma

Git İleri Düzey: Her Hafta Saatler Kazandıran İş Akışları

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

Paylaş:X / TwitterLinkedIn

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

Interactive Rebase: Kimse Görmeden Karmaşayı Temizle#

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.

Temel Komut#

bash
git rebase -i HEAD~5

Bu, son 5 commit'ini en eskiden en yeniye gösteren bir editör açar:

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

Her satır bir komutla başlar. pick'i şunlardan biriyle değiştir:

  • squash (veya s) — Bu commit'i üsttekiyle birleştir, mesajları birleştir
  • fixup (veya f) — Squash gibi, ama bu commit'in mesajını at
  • reword (veya r) — Commit'i koru ama mesajını değiştir
  • drop (veya d) — Bu commit'i tamamen sil
  • edit (veya e) — Rebase'i bu commit'te duraklat, amend edebilsin

Gerçek Bir Temizlik Oturumu#

İşte gerçekte yaptığım şey. Yukarıdaki dağınık geçmiş şöyle olur:

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

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

Commit'leri Yeniden Sıralama#

Satırları kelimenin tam anlamıyla yeniden düzenleyebilirsin. Test commit'i rate limiting'den önce gelmeli ise, satırı taşı:

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

Git commit'lerini bu yeni sırada tekrar oynatır. Çakışma varsa durur ve çözmene izin verir.

Autosquash Kısayolu#

Bir commit'in öncekinin düzeltmesi olduğunu commit zamanında biliyorsan, commit'lerken işaretle:

bash
git commit --fixup=a1b2c3d

Bu, fixup! Add user authentication endpoint mesajlı bir commit oluşturur. Sonra rebase yaptığında:

bash
git rebase -i --autosquash HEAD~5

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

Altın Kural#

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:

bash
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: Cerrahi Commit Transferi#

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ış.

Gerçekte Ne Zaman Kullanıyorum#

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.

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

Tamam. Düzeltme main'de aynı değişikliklerle yeni bir commit olarak var.

Commit Yapmadan Cherry-Pick#

Bazen değişiklikleri uygulamak ama henüz commit'lememek istersin:

bash
git cherry-pick --no-commit a1b2c3d

Değişiklikler staged ama commit edilmemiş. Değiştirebilir, daha fazla değişiklik ekleyebilir, hazır olunca commit edebilirsin.

Aralıklı Cherry-Pick#

Ardışık birden fazla commit mi gerekiyor? Aralık sözdizimini kullan:

bash
git cherry-pick a1b2c3d..f6g7h8i

Çakışmaları Yönetmek#

Cherry-pick çakışmaları merge çakışmaları gibi çalışır:

bash
# Git bir çakışma olduğunu söyleyecek
# Çakışan dosyaları düzelt, sonra:
git add .
git cherry-pick --continue

Veya vazgeçtiysen:

bash
git cherry-pick --abort

Git Bisect: Bug'lar İçin İkili Arama#

Bir ş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.

Manuel Yol#

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

Git iyi ile kötü arasında yarıdaki bir commit'i checkout eder. Test et. Sonra:

bash
# Bug bu commit'te varsa:
git bisect bad
 
# Bug bu commit'te yoksa:
git bisect good

Git aralığı her seferinde yarıya böler. 7-8 adım sonra şunu söyler:

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

Artık tam olarak hangi commit'in bug'ı tanıttığını biliyorsun. İşin bittiğinde:

bash
git bisect reset

Otomatik Yol (Asıl Güç Budur)#

Bug'ı tespit edebilen bir testin varsa, her şeyi otomatikleştirebilirsin:

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

Git Worktree: Birden Fazla Dal, Sıfır Stash#

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:

  1. Her şeyi stash'le, dal değiştir, düzelt, geri dön, stash'i pop et. Hiçbir şeyin ters gitmeyeceğini um.
  2. Yarım kalmış işini "wip" mesajıyla commit'le. Çirkin ama işlevsel.
  3. Repo'yu başka bir dizine tekrar klonla.

Ya da seçenek 4: worktree.

Worktree Nedir#

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.

Worktree Ekleme#

bash
# feature/user-auth dalındasın, işin içindesin
# main'de bir bug düzeltmen gerekiyor:
 
git worktree add ../hotfix-session main

Bu, 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.

bash
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

Worktree'leri Yönetme#

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

Bu Neden Stash'ten İyi#

Stash hızlı bağlam değişiklikleri için iyi. Ama worktree'ler beş dakikadan fazla sürecek her şey için daha iyi:

  • IDE'n feature dalında açık kalır. Yeniden indeksleme yok, scroll pozisyonunu kaybetme yok.
  • Her iki dizinde aynı anda test çalıştırabilirsin.
  • Stash çakışması veya neyi stash'lediğini unutma riski yok.
  • Bir worktree'de uzun süren dev server, diğerinde temiz build olabilir.

Reflog: Her Şey İçin Geri Al Butonu#

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.

Reflog Nedir#

HEAD her hareket ettiğinde — her commit, checkout, rebase, reset, merge — Git bunu reflog'a kaydeder.

bash
git reflog

Çıktı:

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

Hard Reset Sonrası Kurtarma#

Yanlışlıkla git reset --hard HEAD~3 çalıştırdın ve üç commit'i kaybettin. Reflog'da duruyorlar:

bash
# Neyi kaybettiğini gör
git reflog
 
# Reset'ten önceki commit HEAD@{1}
git reset --hard f4e5d6c

Üç commit geri geldi. Kriz önlendi.

Silinen Dalı Kurtarma#

Merge edilmemiş işi olan bir dalı sildin:

bash
git branch -D feature/experimental
# Hayır, orada iki haftalık iş vardı

Commit'ler hâlâ var. Bul:

bash
git reflog | grep "feature/experimental"
 
# Buldun. Dalı o commit'te yeniden oluştur:
git branch feature/experimental a1b2c3d

Dal tüm commit'leriyle geri döndü.

Kötü Rebase Sonrası Kurtarma#

Rebase yaptın ve her şey ters gitti:

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

Rebase başlamadan önceki haline döndün. Sanki hiç olmamış gibi.

Stash'i Düzgün Kullan#

Çoğu kişi stash'i şöyle kullanır:

bash
git stash
# bir şey yap
git stash pop

Bu çalışır, ama her şeyi "eşyalar" etiketli bir kutuya atmaya eşdeğer.

Stash'lerine İsim Ver#

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

İzlenmeyen Dosyaları Dahil Et#

bash
# Yeni dosyalar dahil her şeyi stash'le
git stash push --include-untracked -m "WIP: new auth components"

Kısmi Stash#

Belirli dosyaları stash'leyebilirsin:

bash
# Sadece belirli dosyaları stash'le
git stash push -m "Just the auth changes" src/auth/ src/middleware.ts

Dallanma Stratejileri: Hangisi Gerçekten Çalışıyor#

Gitflow#

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

GitHub Flow#

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.

Trunk-Based Development#

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.

Benim Tavsiyem#

Ç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ç.

Git Hook'ları: Sürekli Unuttuğun Şeyleri Otomatikleştir#

pre-commit — Her commit'ten önce çalışır. Linting ve formatlama için kullan:

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

commit-msg — Commit mesajı formatını doğrular:

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 "Invalid commit message format."
  echo "Expected: type(scope): description"
  exit 1
fi

Husky vs Native Hook'lar#

Husky hook yapılandırmalarını repo'da saklar ve npm install'da .git/hooks'u otomatik kurar:

bash
npx husky init

lint-staged ile birleştirildiğinde hızlı, hedefli pre-commit kontrolleri elde edersin:

json
{
  "lint-staged": {
    "*.{js,ts,tsx}": ["eslint --fix", "prettier --write"],
    "*.css": ["prettier --write"],
    "*.json": ["prettier --write"]
  }
}

Zaman Kazandıran Alias'lar#

Pretty Log#

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

Son Commit'i Geri Al#

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

Daha Fazla Kullandığım Alias'lar#

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

Her Gün Kullandığım Komutlar#

Staged Değişiklikleri Diff'le#

bash
git diff --staged

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

Belirli Bir Commit'i Göster#

bash
git show a1b2c3d

Satır Aralıklı Blame#

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

42-60 arasındaki satırları kimin en son değiştirdiğini gösterir.

Tüm Geçmişte String Ara#

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

Her Şeyi Bir Araya Koyma: Gerçek Bir İş Akışı#

Tipik bir gün bu araçlarla şöyle görünür:

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

İlgili Yazılar