Rebase Nedir?
Giriş — Tarihçeyi Yeniden Yazmak
Git'in en güçlü ve en tartışmalı özelliğine hoş geldin: rebase. Bu komut, commit tarihçesini yeniden yazmana olanak tanır. Doğru kullanıldığında tarihçeni tertemiz yapar; yanlış kullanıldığında ekip arkadaşlarının bir günlük çalışmasını çöpe atabilir.
Merge'ü zaten biliyorsun — iki branch'i birleştirir, bir merge commit oluşturur. Rebase ise farklı bir yaklaşım sunar: "Branch'imi sanki en baştan bu noktadan açmışım gibi yeniden uygula." Tarihçe lineer, temiz ve okunaklı olur.
Bu derste hem temel rebase'i hem de çok güçlü olan interactive rebase'i detaylıca öğreneceksin.
Merge vs Rebase — Temel Fark
Analoji — İki Farklı Hikaye Anlatma Biçimi
Bir arkadaşın sana hafta sonunu anlatıyor. İki farklı anlatım tarzı düşün:
Merge tarzı anlatım (kronolojik birleştirme): "Cumartesi sabah kahvaltı yaptım. Bu arada sen film izlemişsin. Sonra ben sinemaya gittim. Aynı zamanda sen markete gitmişsin. Pazar günü buluştuk ve her şeyi birleştirdik."
Rebase tarzı anlatım (lineer hikaye): "Sen şunları yaptın: film izledin, markete gittin. Sonra ben şunları yaptım: kahvaltı yaptım, sinemaya gittim. Ve pazar buluştuk."
Merge her iki tarihçeyi olduğu gibi koruyup bir birleştirme noktası oluşturur. Rebase ise bir tarihçeyi diğerinin ucuna "yeniden uygular" — sanki her şey sıralı olmuş gibi.
Görsel Karşılaştırma
Başlangıç durumu:
main A───B───C
\
feature D───EMerge sonrası:
main A───B───C───────M (M = merge commit)
\ /
feature D───E───┘Rebase sonrası:
main A───B───C
\
feature D'───E' (D ve E yeniden uygulandı)Rebase'den sonra fast-forward merge yapılırsa:
main A───B───C───D'───E' (tamamen lineer!)Temel Rebase Kullanımı
Senaryo: Feature Branch'i Güncelleme
# Durum: main branch ilerledı, feature branch geride kaldı
# main: A → B → C → F → G (F ve G yeni commit'ler)
# feature: A → B → C → D → E (D ve E senin commit'lerin)
# Feature branch'tesin
git checkout feature/login
# main'deki yeni commit'leri feature'ın altına al
git rebase mainTerminal çıktısı:
First, rewinding head to replay your work on top of it...
Applying: Add login form component
Applying: Add login validation logic
Successfully rebased and updated refs/heads/feature/login.Rebase Ne Yapar? (Adım Adım)
ADIM 1: feature branch'teki commit'leri "sakla"
(D ve E commit'lerini kenara koy)
ADIM 2: feature branch'i main'in ucuna taşı
(HEAD artık G'yi gösteriyor)
ADIM 3: Saklanan commit'leri sırasıyla yeniden uygula
D → D' (yeni hash ile)
E → E' (yeni hash ile)
SONUÇ:
main A───B───C───F───G
\
feature D'───E'⚠️ Dikkat: Rebase commit hash'lerini değiştirir! D ve E artık D' ve E' oldu. İçerik aynı, ama farklı commit'ler. Bu, paylaşılmış branch'lerde tehlikeli olabilir.
Rebase Sonrası Fast-Forward Merge
# Rebase'den sonra main'e geç ve merge et
git checkout main
git merge feature/login # Bu bir fast-forward merge olur!Updating abc1234..def5678
Fast-forward
src/login.js | 42 +++++++++++++++++++++++++++++++++
1 file changed, 42 insertions(+)Sonuç: Tamamen lineer, temiz bir tarihçe:
main A───B───C───F───G───D'───E'Rebase Conflict Çözme
Rebase sırasında da conflict çıkabilir. Ama merge'den farklı olarak, her commit tek tek uygulanır — yani her commit'te ayrı conflict olabilir.
git rebase mainConflict çıkarsa:
CONFLICT (content): Merge conflict in src/config.js
error: could not apply abc1234... Update config
Resolve all conflicts manually, mark them as resolved with
"git add <pathspec>" then run "git rebase --continue".
hint: Or use "git rebase --skip" to skip this commit.
hint: Or use "git rebase --abort" to abort the rebase.Conflict Çözüm Adımları
# 1. Conflict'li dosyayı aç ve düzelt
# <<<<<<< HEAD, ======= ve >>>>>>> işaretlerini temizle
# 2. Düzelttiğini işaretle
git add src/config.js
# 3. Rebase'e devam et
git rebase --continue
# Eğer bu commit'i atlamak istiyorsan:
git rebase --skip
# Eğer vazgeçmek istiyorsan (her şeyi geri al):
git rebase --abortConflict Akışı
Commit D uygulanıyor... ──── Conflict! ──► Çöz → git add → git rebase --continue
│
Commit E uygulanıyor... ──── Conflict! ──► Çöz → git add → git rebase --continue
│
▼
Successfully rebased ✅Interactive Rebase — Git'in İsviçre Çakısı
Interactive rebase (git rebase -i), Git'in en güçlü araçlarından biridir. Commit'lerin üzerinde tam kontrol sağlar: sıralama, birleştirme, düzenleme, silme, mesaj değiştirme…
Analoji — Video Düzenleme
Bir video çektin. Ham haliyle paylaşmak yerine video düzenleme programında açıyorsun:
Bazı sahneleri birleştiriyorsun (squash)
Bazılarının açıklamasını değiştiriyorsun (reword)
Bazılarını kırpıyorsun (edit)
Bazılarını tamamen siliyorsun (drop)
Sahnelerin sırasını değiştiriyorsun (reorder)
Interactive rebase, commit tarihçeni bir video gibi düzenlemeni sağlar.
Kullanım
# Son 4 commit'i düzenle
git rebase -i HEAD~4
# Belirli bir commit'ten itibaren düzenle
git rebase -i abc1234
# Branch'in ayrıldığı noktadan itibaren düzenle
git rebase -i mainBu komutu çalıştırdığında editörde şöyle bir dosya açılır:
pick abc1234 feat: Add user model
pick def5678 fix: Fix typo in user model
pick ghi9012 WIP: Working on validation
pick jkl3456 feat: Add validation logic
# Rebase abc1234..jkl3456 onto 789xyz (4 commands)
#
# Commands:
# p, pick = use commit as is (commit'i olduğu gibi kullan)
# r, reword = use commit, but edit the commit message (mesajı değiştir)
# e, edit = use commit, but stop for amending (commit'i düzenle)
# s, squash = use commit, but meld into previous commit (öncekiyle birleştir)
# f, fixup = like "squash", but discard this commit's log message (sessiz birleştir)
# d, drop = remove commit (commit'i sil)
#
# These lines can be re-ordered; they are executed from top to bottom.
# If you remove a line here, THAT COMMIT WILL BE LOST.Interactive Rebase Komutları Detaylı
1. pick — Olduğu Gibi Kullan
pick abc1234 feat: Add user modelCommit'i değiştirmeden kullan. Varsayılan davranış.
2. reword — Commit Mesajını Değiştir
reword abc1234 feat: Add user modelCommit'in içeriği aynı kalır, sadece mesajı değiştirebilirsin. Kaydettiğinde yeni bir editör açılır ve mesajı düzenlersin.
# Örnek: Typo düzeltme
# "feat: Add usr model" → "feat: Add user model"3. squash — Önceki Commit ile Birleştir
pick abc1234 feat: Add user model
squash def5678 fix: Fix typo in user modelİki commit tek bir commit'e birleşir. Her iki commit'in mesajı da editörde gösterilir — düzenleyebilirsin:
# This is a combination of 2 commits.
# This is the 1st commit message:
feat: Add user model
# This is the commit message #2:
fix: Fix typo in user model
# Düzenle ve kaydet:
feat: Add user model with proper naming4. fixup — Sessiz Birleştirme
pick abc1234 feat: Add user model
fixup def5678 fix: Fix typo in user modelSquash gibi birleştirir ama ikinci commit'in mesajını atar. Sonuç sadece "feat: Add user model" olur. "fix typo", "WIP" gibi anlamsız commit'leri temizlemek için harika.
5. edit — Commit'i Düzenle
edit abc1234 feat: Add user modelRebase bu commit'te durur. İstediğin değişiklikleri yapabilirsin:
# Rebase durdu, düzenle:
# Dosya ekle, değiştir, sil...
git add src/user.js
git commit --amend # Bu commit'i güncelle
git rebase --continue # Devam etBir commit'i iki commit'e bölmek için de kullanılır:
edit abc1234 feat: Add user model and validation # Bu çok büyük bir commit
# Rebase durduğunda:
git reset HEAD~1 # Commit'i geri al (dosyalar working directory'de kalır)
# İki ayrı commit yap:
git add src/models/user.js
git commit -m "feat: Add user model"
git add src/validators/user.js
git commit -m "feat: Add user validation"
git rebase --continue6. drop — Commit'i Sil
drop ghi9012 WIP: Working on validationBu commit tamamen tarihçeden silinir. Satırı silmek de aynı etkiyi yapar.
⚠️ Dikkat:
dropedilen commit geri gelmez (reflog hariç). Emin olmadan kullanma!
Pratik Interactive Rebase Senaryoları
Senaryo 1: Commit'leri Temizleme (En Yaygın)
PR'ında şu commit'ler var:
abc1234 feat: Add shopping cart
def5678 WIP
ghi9012 fix typo
jkl3456 still working on it
mno7890 feat: Add checkout flow
pqr1234 forgot to add fileBu tarihçeyi temizleyelim:
git rebase -i HEAD~6Editörde:
pick abc1234 feat: Add shopping cart
fixup def5678 WIP
fixup ghi9012 fix typo
fixup jkl3456 still working on it
pick mno7890 feat: Add checkout flow
fixup pqr1234 forgot to add fileSonuç — tertemiz iki commit:
feat: Add shopping cart
feat: Add checkout flowSenaryo 2: Commit Sırasını Değiştirme
git rebase -i HEAD~3Editörde satırları taşı (kes-yapıştır):
# Önce:
pick abc1234 feat: Add API
pick def5678 feat: Add Database
pick ghi9012 feat: Add Models
# Sonra (sırayı değiştir):
pick def5678 feat: Add Database
pick ghi9012 feat: Add Models
pick abc1234 feat: Add APISenaryo 3: Commit Mesajlarını Düzenleme
git rebase -i HEAD~3reword abc1234 addd user loginn # typo'lu mesaj
pick def5678 feat: Add logout
pick ghi9012 feat: Add profile pageKaydedince yeni bir editör açılır:
# Eski mesajı düzenle:
feat: Add user loginSenaryo 4: Autosquash ile fixup! ve squash! Commit'leri
Git'in akıllı bir özelliği: commit mesajına fixup! veya squash! öneki koyarsan, interactive rebase otomatik olarak doğru yere yerleştirir.
# Ana commit
git commit -m "feat: Add user dashboard"
# Sonra bir düzeltme yaptın
git commit -m "fixup! feat: Add user dashboard"
# Interactive rebase ile otomatik birleştir
git rebase -i --autosquash HEAD~5Editörde otomatik olarak düzenlenir:
pick abc1234 feat: Add user dashboard
fixup def5678 fixup! feat: Add user dashboard # Otomatik yerleşti!
pick ghi9012 feat: Add settings page💡 İpucu:
git config --global rebase.autoSquash trueile autosquash'ı varsayılan olarak açabilirsin. Hergit rebase -iotomatik olarak fixup!/squash! commit'lerini düzenler.
The Golden Rule of Rebasing
Git dünyasının en önemli kuralı:
╔══════════════════════════════════════════════════════════════╗
║ ║
║ 🏆 ALTIN KURAL: ║
║ ║
║ Paylaşılmış (push edilmiş) commit'leri ║
║ ASLA rebase etme! ║
║ ║
╚══════════════════════════════════════════════════════════════╝Neden?
Rebase commit hash'lerini değiştirir. Eğer başka birisi senin eski commit'lerini baz alarak çalışıyorsa, rebase sonrası her şey bozulur:
SENARYO: Ahmet ve Sen aynı branch üzerinde çalışıyorsunuz
Başlangıç (ikisinde de aynı):
main A───B───C
Sen rebase yaptın:
main A───B'───C' (hash'ler değişti!)
Ahmet hâlâ eski versiyonda:
main A───B───C
Ahmet push etmeye çalışıyor: CONFLICT!
Ahmet pull yapıyor: Aynı değişiklikler iki kere görünüyor!
KAOS. 💥Ne Zaman Rebase Güvenli?
✅ GÜVENLİ:
- Henüz push etmediğin yerel commit'ler
- Sadece SENİN çalıştığın feature branch
- PR'ı merge etmeden önce temizlik (squash)
❌ TEHLİKELİ:
- main/develop branch'i (paylaşımlı)
- Başkalarının da push ettiği branch'ler
- Zaten merge edilmiş commit'lerForce Push Gereksinimi
Rebase yaptıktan sonra push etmek istersen, normal git push çalışmaz çünkü tarihçe değişti:
# ❌ Normal push başarısız olur:
git push
# ! [rejected] feature -> feature (non-fast-forward)
# ✅ Force push gerekir:
git push --force-with-lease
# ❌ Asla çıplak --force kullanma:
git push --force # Başkasının push'unu ezebilir!--force-with-lease farkı:
--force → "Ne olursa olsun, remote'u benim versiyonumla değiştir"
--force-with-lease → "Remote son gördüğüm haldeyse değiştir,
birisi push ettiyse DURDUR"💡 İpucu:
git config --global alias.pushf 'push --force-with-lease'ile kısaltma tanımla. Artıkgit pushfyeterli.
Rebase vs Merge — Hangisini Seçmeli?
Karar Ağacı
Branch sadece benim mi?
├── Evet → Rebase kullan (temiz tarihçe)
│ git pull --rebase
│ git rebase main
│
└── Hayır (paylaşımlı branch)
├── Merge kullan (güvenli)
│ git merge main
│
└── Rebase istiyorsan:
→ Ekiple konuş, herkes aynı anda güncellesin
→ git push --force-with-leaseKarşılaştırma
┌────────────────────┬──────────────────┬──────────────────┐
│ Özellik │ Merge │ Rebase │
├────────────────────┼──────────────────┼──────────────────┤
│ Tarihçe │ Dallı, karmaşık │ Lineer, temiz │
│ Merge commit │ Var │ Yok │
│ Orijinal commit │ Korunur │ Hash değişir │
│ Conflict çözümü │ Bir kez │ Her commit'te │
│ Güvenlik │ Güvenli │ Dikkat gerekir │
│ Paylaşımlı branch │ ✅ Uygun │ ⚠️ Tehlikeli │
│ git log okuması │ Karmaşık │ Kolay │
│ Revert kolaylığı │ Kolay │ Zor olabilir │
│ Branch ilişkisi │ Görünür │ Kaybolur │
└────────────────────┴──────────────────┴──────────────────┘Ekip Stratejileri
Strateji 1: "Merge Everything" (Güvenli)
Her branch merge edilir. Tarihçe karmaşık ama güvenli.
Strateji 2: "Rebase + Merge" (Temiz)
Feature branch'i rebase et, sonra merge (fast-forward).
Temiz tarihçe ama dikkat gerekir.
Strateji 3: "Squash + Merge" (Pratik)
Feature branch'teki tüm commit'ler squash edilir.
Her PR = tek commit. En yaygın tercih.
Strateji 4: "Rebase + Squash" (Titiz)
Önce interactive rebase ile commit'leri temizle,
sonra squash merge yap. En temiz tarihçe.git pull --rebase
git pull aslında git fetch + git merge dir. Ama --rebase parametresiyle git fetch + git rebase yaparsın:
# Normal pull (merge oluşturur):
git pull origin main
# fetch + merge → merge commit oluşabilir
# Rebase pull (lineer kalır):
git pull --rebase origin main
# fetch + rebase → merge commit oluşmazVarsayılan Olarak Ayarlama
# Tüm pull'ları rebase modunda yap
git config --global pull.rebase true
# Sadece bu repo için
git config pull.rebase trueBu ayar özellikle birden fazla kişinin aynı branch'te çalıştığı (pek önerilmese de) durumlarda gereksiz merge commit'leri önler.
--onto ile Gelişmiş Rebase
Bazen bir branch'i farklı bir noktaya taşımak istersin. --onto bunu sağlar.
Senaryo: Branch'i Farklı Bir Base'e Taşıma
# Durum: feature branch'i yanlışlıkla eski bir noktadan açtın
main A───B───C───D───E
\
old-feature F───G
\
sub-feature H───I ← Bunu main'in ucuna taşımak istiyorsun# sub-feature'ı old-feature'dan kopar, main'in ucuna bağla
git rebase --onto main old-feature sub-feature# Sonuç:
main A───B───C───D───E
\ \
old-feature F───G H'───I' (sub-feature)--onto Sözdizimi
git rebase --onto <yeni-base> <eski-base> <branch>
# "branch'teki eski-base'den sonraki commit'leri al,
# yeni-base'in üzerine uygula"Rebase Sorun Giderme
"Rebase yaptım ama korkuyorum"
# Rebase'den önceki duruma dönmek her zaman mümkün:
git reflog
# abc1234 HEAD@{2}: rebase finished: refs/heads/feature onto def5678
# ghi9012 HEAD@{3}: rebase: checkout main
# jkl3456 HEAD@{4}: commit: feat: last commit before rebase ← BU!
git reset --hard jkl3456 # Rebase'den önceki hale dön"Conflict çok fazla, vazgeçiyorum"
git rebase --abort # Her şeyi geri al, rebase başlamadan önceki hale dön"Bu commit'i atlamak istiyorum"
git rebase --skip # Bu commit'i atlayıp devam etÖzet
Bu derste Git'in en güçlü tarihçe aracı olan rebase'i öğrendik:
Rebase, commit'leri başka bir noktanın üzerine yeniden uygular — merge'den farklı olarak lineer bir tarihçe oluşturur
Interactive rebase (
git rebase -i) ile commit'leri düzenleyebilir, birleştirebilir, silebilir, sıralayabilirsin — pick, reword, squash, fixup, edit, drop komutlarıyla tam kontrolAltın Kural: Paylaşılmış commit'leri asla rebase etme — hash'ler değişir ve ekip arkadaşlarının tarihçesi bozulur
Force push (
--force-with-lease) rebase sonrası gereklidir ama dikkatli kullanılmalıdırgit pull --rebase ile gereksiz merge commit'lerini önleyebilirsin
Rebase'den dönüş her zaman mümkün:
git rebase --abortveyagit reflogile eski hale dönebilirsin
Bir sonraki derste commit tarihçesinin dedektifi olacağız: cherry-pick, bisect ve blame.
AI Asistan
Sorularını yanıtlamaya hazır