Push ve Pull
Giriş: Neden Push ve Pull Bu Kadar Önemli?
Git'in dağıtık yapısı sayesinde herkes kendi yerel repo'sunda bağımsız çalışabilir. Ama bir noktada kodunu paylaşman ve başkalarının kodunu alman gerekiyor. İşte push ve pull bu köprüyü kurar.
Bu iki komut her gün onlarca kez kullanacağın komutlar. Doğru kullanmak rahat, yanlış kullanmak felaket. Özellikle --force bayrağı, dikkatsiz kullanıldığında başkalarının çalışmalarını silebilir.
Bu derste:
git push'un tüm varyasyonlarıgit pull'un farklı modları--force-with-leasenedir ve neden--force'tan daha güvenlidirYaygın senaryolar ve çözümleri
🎬 Analoji: Paylaşılan Belge
Google Docs'ta bir belge düşün:
Push = Senin değişikliklerini belgeye yükleme. "Benim yazdıklarım artık herkesin görebileceği yerde."
Pull = Belgede başkalarının yaptığı değişiklikleri alma. "Ayşe ne eklemiş, bakayım."
Force Push = Belgenin tüm geçmişini kendi versiyonunla değiştirme. "Herkesin yazdığını silip benim versiyonumu koydum." ⚠️ Tehlikeli!
git push — Kodunu Gönder
Temel Kullanım
# Genel sözdizimi
$ git push <remote> <branch>
# En yaygın kullanım
$ git push origin main
Enumerating objects: 5, done.
Counting objects: 100% (5/5), done.
Delta compression using up to 8 threads
Compressing objects: 100% (3/3), done.
Writing objects: 100% (3/3), 350 bytes | 350.00 KiB/s, done.
Total 3 (delta 1), reused 0 (delta 0)
To https://github.com/tolgahan/projem.git
a1b2c3d..d4e5f6g main -> mainBu çıktıyı okuyalım:
Git nesneleri sıkıştırılıp gönderildi
a1b2c3d..d4e5f6g— önceki commit'ten yeni commit'e güncellendimain -> main— yerelmain'den remotemain'e
--set-upstream (-u): Bağlantı Kur
İlk push'ta -u bayrağı ile yerel branch'i remote branch'e bağlarsın:
# İlk push
$ git push -u origin main
Branch 'main' set up to track remote branch 'main' from 'origin'.
# Bundan sonra sadece şu yeterli:
$ git push
# origin main'i otomatik bilir
$ git pull
# origin main'den otomatik çekerYeni bir feature branch için:
$ git switch -c feature/search
# ... çalış, commit at ...
$ git push -u origin feature/search
# İlk push'ta -u kullan
# Sonrakilerinde sadece git push yeterlipush Çıktıları ve Anlamları
# Başarılı push
$ git push
To https://github.com/tolgahan/projem.git
a1b2c3d..d4e5f6g main -> main
# ✅ Sorunsuz gönderildi
# Reddedilen push
$ git push
To https://github.com/tolgahan/projem.git
! [rejected] main -> main (fetch first)
error: failed to push some refs to 'https://github.com/...'
hint: Updates were rejected because the remote contains work that
hint: you do not have locally. Integrate the remote changes
hint: (e.g., 'git pull ...') before pushing again.
# ❌ Reddedildi — remote'ta sende olmayan commit'ler varRejected durumu: Birileri senden önce push etmiş. Önce pull yapıp değişiklikleri birleştirmen gerekiyor:
# 1. Remote'taki değişiklikleri al
$ git pull origin main
# 2. Conflict varsa çöz (önceki derslerde öğrendik)
# 3. Tekrar push et
$ git push origin mainpush.default Ayarı
# Mevcut branch'i push et (önerilen)
$ git config --global push.default current
# Sadece izlenen branch'i push et
$ git config --global push.default simple # Git 2.x varsayılanı
# Tüm eşleşen branch'leri push et (eski davranış — önerilmez)
$ git config --global push.default matchingTag Push'lama
Tag'ler normal push ile gönderilmez:
# Tek tag push'la
$ git push origin v1.0.0
# Tüm tag'leri push'la
$ git push origin --tags
# Hem commit hem tag push'la
$ git push --follow-tagsgit push --force: Tehlikeli Alan
Neden Force Push Gerekir?
Bazı durumlarda normal push reddedilir ve --force gerekir:
git commit --amendile son commit'i değiştirdingit rebaseyaptınGeçmişi yeniden yazdın (
git reset)
Bu durumların hepsinde commit hash'leri değişir. Remote'taki geçmiş ile senin geçmişin uyumsuz olur.
Remote: [A] ← [B] ← [C]
Yerel: [A] ← [B] ← [C'] ← amend ile C değişti, C' oldu
Normal push: REDDEDILIR (C ≠ C')
Force push: Remote'u senin versiyonla değiştirir--force: Kaba Kuvvet
$ git push --force origin main
# veya kısaca
$ git push -f origin main⚠️ Dikkat:
--forceson derece tehlikelidir. Neden? Çünkü remote'taki commit'leri silip seninkilerle değiştirir. Eğer birileri bu arada push ettiyse, onların commit'leri kaybolur.
Ali: [A] ← [B] ← [C] ← [D] (Ali D'yi push etti)
Sen: [A] ← [B] ← [C'] (C'yi amend ettin)
$ git push --force
Remote: [A] ← [B] ← [C'] (Ali'nin D commit'i SİLİNDİ!)--force-with-lease: Güvenli Force Push
$ git push --force-with-lease origin main--force-with-lease şunu yapar:
"Remote'taki
mainbranch, benim bildiğim commit'i mi gösteriyor?"EVET → force push yap
HAYIR → "Birisi push etmiş, iptal et!" der
Senaryo 1: Kimse push etmemiş
Senin origin/main: [A] ← [B] ← [C] (son fetch'teki durum)
Remote'taki main: [A] ← [B] ← [C] (aynı!)
Senin yerel main: [A] ← [B] ← [C'] (amend)
$ git push --force-with-lease
✅ origin/main beklediğim gibi, push ediyorum.
Senaryo 2: Birisi push etmiş
Senin origin/main: [A] ← [B] ← [C] (son fetch'teki durum)
Remote'taki main: [A] ← [B] ← [C] ← [D] (birisi D'yi push etmiş!)
Senin yerel main: [A] ← [B] ← [C']
$ git push --force-with-lease
❌ REDDEDILDI! Remote değişmiş. Önce fetch yap.Bu, "güvenli force push" demektir. Başkasının çalışmasını kazayla silmezsin.
💡 İpucu:
--forceyerine her zaman--force-with-leasekullan. Alias ekle: ``bash git config --global alias.pushf "push --force-with-lease"`Artıkgit pushf` ile güvenli force push yapabilirsin.
git pull — Güncel Kal
Temel Kullanım
# Remote'tan çek ve birleştir
$ git pull origin main
remote: Enumerating objects: 5, done.
remote: Counting objects: 100% (5/5), done.
remote: Compressing objects: 100% (3/3), done.
Unpacking objects: 100% (3/3), done.
From https://github.com/tolgahan/projem
a1b2c3d..d4e5f6g main -> origin/main
Updating a1b2c3d..d4e5f6g
Fast-forward
index.html | 5 +++++
1 file changed, 5 insertions(+)pull = fetch + merge
# Bu iki komut aynı işi yapar:
$ git pull origin main
$ git fetch origin
$ git merge origin/mainpull --rebase: Temiz Geçmiş
$ git pull --rebase origin main
# veya global ayar:
$ git config --global pull.rebase trueNeden rebase tercih edilir?
Normal pull (merge) sonucunda:
$ git log --oneline --graph
* f7g8h9i Merge branch 'main' of github.com:tolgahan/projem
|\
| * d5e6f7g feat: Ayşe'nin değişikliği
* | c4d5e6f feat: Benim değişikliğim
|/
* a1b2c3d feat: Başlangıç
Pull --rebase sonucunda:
$ git log --oneline --graph
* c4d5e6f' feat: Benim değişikliğim
* d5e6f7g feat: Ayşe'nin değişikliği
* a1b2c3d feat: Başlangıç
Rebase ile gereksiz merge commit oluşmaz. Geçmiş temiz kalır.⚠️ Dikkat:
pull --rebasesırasında conflict çıkabilir. Bu durumda: ``bash # Conflict'i çöz, dosyayı düzenle $ git add dosya.txt $ git rebase --continue # Veya rebase'i iptal et $ git rebase --abort``
pull Stratejisi Ayarları
# Varsayılan pull davranışı
$ git config --global pull.rebase true # Her zaman rebase
$ git config --global pull.rebase false # Her zaman merge (varsayılan)
$ git config --global pull.ff only # Sadece fast-forward, yoksa hata verYaygın Senaryolar ve Çözümleri
Senaryo 1: Push Reddedildi
$ git push origin main
! [rejected] main -> main (fetch first)Çözüm:
# Yol 1: Pull + Push
$ git pull origin main
# (conflict varsa çöz)
$ git push origin main
# Yol 2: Pull --rebase + Push (daha temiz)
$ git pull --rebase origin main
# (conflict varsa çöz, git rebase --continue)
$ git push origin mainSenaryo 2: Amend Sonrası Push
$ git commit -m "feat: Login eklendi"
$ git push origin main
# Push başarılı
# Oops, mesaj yanlış!
$ git commit --amend -m "feat: Login sayfası eklendi"
$ git push origin main
! [rejected] # Hash değişti, reddedildi
# Çözüm: Force with lease
$ git push --force-with-lease origin main
# ✅ Güvenli force pushSenaryo 3: Yanlış Branch'e Push
# Feature branch'ini yanlışlıkla main'e push'ladın
$ git push origin feature/login:main
# 😱
# Düzeltme: main'i eski haline getir
$ git push --force-with-lease origin HEAD~1:main
# veya doğru commit'e reset'leSenaryo 4: Tüm Branch'leri Push
# Tüm yerel branch'leri push et
$ git push --all origin
# Tüm tag'lerle birlikte
$ git push --all origin && git push --tags originSenaryo 5: Remote Branch'i Sil
# Remote'taki branch'i sil
$ git push origin --delete feature/old-feature
To github.com:tolgahan/projem.git
- [deleted] feature/old-featureGünlük Workflow: Push ve Pull
Sabah Rutini
# 1. Günün başında main'i güncelle
$ git switch main
$ git pull origin main
# 2. Feature branch'inde çalışmaya devam et
$ git switch feature/my-work
$ git rebase main
# main'deki yeni değişiklikleri alAkşam Rutini
# 1. Çalışmayı push et
$ git push origin feature/my-work
# 2. Eğer PR açacaksan, push sonrası GitHub'da PR açEkip Senkronizasyonu
# 1. Feature branch'ine main'deki güncel değişiklikleri al
$ git switch feature/my-work
$ git fetch origin
$ git rebase origin/main
# (conflict varsa çöz)
$ git push --force-with-lease origin feature/my-work
# 2. Başkasının feature branch'ini kontrol et
$ git fetch origin
$ git switch -c review/their-feature origin/feature/their-work
# İncele, test etPush/Pull Hızlandırma
Shallow Clone
Büyük projelerde tüm geçmişi indirmek uzun sürer:
# Son 10 commit'i indir (daha hızlı)
$ git clone --depth 10 https://github.com/tolgahan/buyuk-proje.git
# Gerekirse tam geçmişi sonradan al
$ git fetch --unshallowPartial Clone
Büyük dosyaları indirmeden clone'la (Git 2.22+):
# Blob'ları (dosya içerikleri) hemen indirme
$ git clone --filter=blob:none https://github.com/tolgahan/proje.git
# Dosyalar sadece checkout edildiğinde indirilirgit fetch — Push ve Pull'un Temeli
git fetch remote'taki değişiklikleri indirir ama yerel branch'leri güncellemez. Bu, "bak ama dokunma" yaklaşımıdır.
# Tüm remote branch'leri güncelle
$ git fetch origin
# Çıktı:
remote: Enumerating objects: 15, done.
remote: Counting objects: 100% (15/15), done.
remote: Compressing objects: 100% (8/8), done.
Unpacking objects: 100% (8/8), done.
From https://github.com/tolgahan/projem
a1b2c3d..d4e5f6g main -> origin/main
* [new branch] feature/x -> origin/feature/x
# Şimdi ne olduğuna bakabilirsin:
$ git log main..origin/main --oneline
d4e5f6g feat: Yeni özellik eklendi
c3d4e5f fix: Bug düzeltildi
# 2 yeni commit var, henüz merge etmeden görebilirsin
# Beğendiysen merge et:
$ git merge origin/mainfetch vs pull Karşılaştırması
┌──────────────────────────────────────────────┐
│ git fetch │
│ │
│ Remote ──download──► origin/main │
│ (remote tracking ref) │
│ │
│ Yerel main DEĞİŞMEDİ │
│ Working directory DEĞİŞMEDİ │
│ Güvenli — sadece indir, birleştirme │
└──────────────────────────────────────────────┘
┌──────────────────────────────────────────────┐
│ git pull │
│ │
│ Remote ──download──► origin/main │
│ ──merge───► main (yerel) │
│ │
│ Yerel main GÜNCELLENDİ │
│ Working directory GÜNCELLENDİ │
│ Otomatik merge — conflict çıkabilir │
└──────────────────────────────────────────────┘💡 İpucu: Tecrübeli geliştiriciler genellikle
git fetch+git log+git mergeakışını tercih eder. Böylece gelen değişiklikleri önce görür, sonra bilinçli olarak merge eder.git pullaynı şeyi tek adımda yapar ama neyin geldiğini görmeden birleştirir.
Stale Branch Temizleme
Remote'ta silinen branch'ler yerel tracking referanslarında kalır:
# Remote'ta silinmiş branch referanslarını temizle
$ git fetch --prune
# veya otomatik prune ayarı
$ git config --global fetch.prune true
# Hangi remote branch'ler kaldırılmış kontrol et
$ git remote prune origin --dry-run
# Pruning origin
# URL: https://github.com/tolgahan/projem.git
# * [would prune] origin/feature/old-thing
# * [would prune] origin/bugfix/resolvedUpstream Tracking — Branch Bağlantıları
Her yerel branch bir remote branch'i "takip" edebilir (tracking). Bu bağlantı kurulduğunda git push ve git pull parametresiz çalışır:
# Tracking bilgisini gör
$ git branch -vv
feature/login a1b2c3d [origin/feature/login] feat: Login eklendi
* main d4e5f6g [origin/main] feat: Son güncelleme
local-only h7i8j9k Yerel branch (tracking yok)
# Tracking ayarla (mevcut branch için)
$ git branch --set-upstream-to=origin/main main
Branch 'main' set up to track remote branch 'main' from 'origin'.
# Tracking kaldır
$ git branch --unset-upstreamAhead / Behind Bilgisi
Tracking ayarlıyken Git, yerel ve remote arasındaki farkı gösterir:
$ git status
On branch main
Your branch is ahead of 'origin/main' by 2 commits.
(use "git push" to publish your local commits)
# veya
Your branch is behind 'origin/main' by 3 commits, and can be fast-forwarded.
(use "git pull" to update your local branch)
# veya
Your branch and 'origin/main' have diverged,
and have 2 and 3 different commits each, respectively.
(use "git pull" to merge the remote branch into yours)Ahead by 2: Yerel'de 2 commit var, remote'ta yok → push et
Behind by 3: Remote'ta 3 commit var, yerel'de yok → pull et
Diverged 2/3: İkisinde de farklı commit'ler var → pull + pushYaygın Hatalar
1. --force Kullanmak (force-with-lease yerine)
# ❌ Ekip arkadaşının commit'lerini silme riski
$ git push --force origin main
# ✅ Güvenli force push
$ git push --force-with-lease origin main2. Pull Yapmadan Push Etmeye Çalışmak
# ❌ Rejected hatasına panik yapmak
$ git push origin main
! [rejected] main -> main (fetch first)
# ✅ Önce pull, sonra push
$ git pull --rebase origin main
$ git push origin main3. Yanlış Remote'a Push Etmek
# ❌ Fork'un upstream'ine push
$ git push upstream main
# Yetkiniz yoksa hata alırsınız, varsa orijinal repo'ya push
# ✅ Remote'ları kontrol et
$ git remote -v
origin https://github.com/siz/fork.git (push)
upstream https://github.com/original/repo.git (push)
$ git push origin main # Kendi fork'unuza4. Tüm Branch'leri Push Etmek
# ❌ WIP branch'lerini de push etmek
$ git push --all origin
# Yarım kalmış, deneme branch'leri de remote'a gider
# ✅ Sadece çalıştığın branch'i push et
$ git push origin feature/my-work5. Büyük Dosyaları Push Etmek
# ❌ GitHub'ın 100MB limiti
$ git push origin main
# remote: error: File data.csv is 150.00 MB; exceeds 100.00 MB limit
# ✅ Büyük dosyaları .gitignore'a ekle veya Git LFS kullan
$ echo "*.csv" >> .gitignore
# veya
$ git lfs track "*.csv"Push ve Pull Komut Referansı
# PUSH
git push # Varsayılan remote'a push
git push origin main # Belirli remote ve branch
git push -u origin feature/x # İlk push + upstream ayarla
git push --force-with-lease # Güvenli force push
git push --tags # Tag'leri push
git push origin --delete branch # Remote branch sil
git push --all origin # Tüm branch'leri push
# PULL
git pull # Varsayılan remote'tan pull
git pull origin main # Belirli remote ve branch
git pull --rebase # Rebase ile pull
git pull --rebase origin main # Belirli remote + rebase
git pull --ff-only # Sadece fast-forward
# FETCH
git fetch # Varsayılan remote'tan fetch
git fetch origin # Belirli remote'tan fetch
git fetch --all # Tüm remote'lardan fetch
git fetch --prune # Silinen branch'leri temizle
git fetch origin branch:local # Uzak branch'i yerel branch'e indirÖzet
`git push` yerel commit'leri remote'a gönderir — ilk push'ta
-uile upstream bağlantısı kur`git pull` = fetch + merge; remote'taki değişiklikleri alır ve yerel branch'le birleştirir
`--rebase` ile pull yaparak gereksiz merge commit'lerini önle —
pull.rebase trueayarı önerilir`--force` yerine `--force-with-lease` kullan — başkasının çalışmasını kazayla silmeyi önler
Push reddedilirse önce
pull(veyapull --rebase) yap, sonra tekrar push'laRemote branch silmek için
git push origin --delete branch-adıkullan
*Bir sonraki derste clone ve fork kavramlarını — projeleri indirme, fork workflow ve open source katkı — öğreneceğiz!*
AI Asistan
Sorularını yanıtlamaya hazır