← Kursa Dön
📄 Text · 30 min

Pull Request

Giriş — Kodunu Teslim Etmeden Önce

Bir yazılım ekibinde çalıştığını düşün. Yeni bir özellik geliştirdin, testlerini yazdın, her şey güzel çalışıyor. Şimdi bu kodu ana branch'e (main) göndermen gerekiyor. Ama direkt push mu edeceksin?

Hayır. Çünkü:

  • Kod kalitesini kim kontrol edecek?

  • Takım arkadaşların değişikliklerden haberdar olacak mı?

  • Bir hata varsa, main branch bozulursa ne olacak?

İşte Pull Request (kısaca PR), tam da bu sorunları çözmek için var. PR, "kodumu ana dalınıza almak istiyorum, lütfen inceleyin" demenin resmi yoludur.


Pull Request Nedir?

Analoji — Bir Makaleyi Yayınlamadan Önce

Bir gazeteci düşün. Makalesini yazıp direkt baskıya vermez. Önce editörüne gönderir. Editör okur, notlar düşer: "Bu paragraf belirsiz", "Bu iddiayı kaynakla destekle", "Başlık daha çarpıcı olabilir". Gazeteci düzeltir, tekrar gönderir. Editör onaylar, makale yayınlanır.

Pull Request tam olarak bu süreçtir:

Gazeteci (Yazar)      →  Developer (Branch'te çalışan)
Makale                 →  Kod değişiklikleri
Editör                 →  Reviewer (Kod inceleyici)
Editoryal notlar       →  Code review yorumları
Yayın onayı           →  PR approval + merge
Gazete baskısı        →  main branch'e merge

Teknik Tanım

Pull Request, bir branch'teki değişiklikleri başka bir branch'e (genellikle main veya develop) birleştirme isteğidir. GitHub bu isteği bir tartışma alanı haline getirir: değişiklikleri görebilir, yorum yapabilir, onaylayabilir veya reddedebilirsin.

feature/login ─── commit ─── commit ─── commit
                                         │
                                    Pull Request
                                         │
                                         ▼
main ─────────────────────────── merge commit

PR Oluşturma Süreci

Adım 1: Branch Oluştur ve Çalış

# Ana branch'ten yeni bir feature branch oluştur
git checkout main
git pull origin main
git checkout -b feature/user-authentication

# Kodunu yaz...
# Dosyaları düzenle, test et

# Commit'le
git add .
git commit -m "feat: add user authentication with JWT"

# Birkaç commit daha...
git add .
git commit -m "feat: add login and register endpoints"

git add .
git commit -m "test: add auth unit tests"

Adım 2: Push Et

git push -u origin feature/user-authentication

Terminal çıktısı:

Enumerating objects: 15, done.
Counting objects: 100% (15/15), done.
Delta compression using up to 8 threads
Compressing objects: 100% (10/10), done.
Writing objects: 100% (12/12), 2.45 KiB | 2.45 MiB/s, done.
Total 12 (delta 5), reused 0 (delta 0)
remote: Resolving deltas: 100% (5/5), completed with 2 local objects.
remote:
remote: Create a pull request for 'feature/user-authentication' on GitHub by visiting:
remote:   https://github.com/username/project/pull/new/feature/user-authentication
remote:
To github.com:username/project.git
 * [new branch]      feature/user-authentication -> feature/user-authentication
Branch 'feature/user-authentication' set up to track remote branch 'feature/user-authentication' from 'origin'.

💡 İpucu: Git push yaptıktan sonra terminal'de PR oluşturma linki verir. Bu linke tıklayarak doğrudan PR sayfasına gidebilirsin.

Adım 3: PR Oluştur (Web Arayüzü)

GitHub'da repo sayfasına git. Üstte sarı bir banner görürsün:

┌──────────────────────────────────────────────────────────────┐
│ 🔔 feature/user-authentication had recent pushes 2 min ago  │
│                              [Compare & pull request]        │
└──────────────────────────────────────────────────────────────┘

Compare & pull request butonuna tıkla. PR formunu doldur:

base: main  ←  compare: feature/user-authentication

Title: feat: Add user authentication with JWT

Description:
## Neler Değişti?
- JWT tabanlı kullanıcı kimlik doğrulama sistemi eklendi
- Login ve register endpoint'leri oluşturuldu
- Birim testleri yazıldı

## Test Edildi mi?
- [x] Unit testler geçiyor
- [x] Manuel test yapıldı
- [ ] Integration test (henüz yok, sonraki PR'da)

## Ekran Görüntüsü
(API endpoint'leri için Postman screenshot'ı)

## İlgili Issue
Closes #42

Reviewers:    @ahmet @ayse
Assignees:    @ben
Labels:       feature, authentication
Milestone:    v1.0

Adım 3 (Alternatif): PR Oluştur (GitHub CLI)

# Basit PR oluşturma
gh pr create --title "feat: Add user authentication" --body "JWT auth sistemi eklendi"

# Detaylı PR oluşturma
gh pr create \
  --title "feat: Add user authentication with JWT" \
  --body "## Değişiklikler
- JWT auth eklendi
- Login/register endpoint'leri

Closes #42" \
  --reviewer ahmet,ayse \
  --assignee @me \
  --label "feature,authentication" \
  --milestone "v1.0"

# İnteraktif mod (adım adım sorar)
gh pr create

gh pr create interaktif çıktısı:

Creating pull request for feature/user-authentication into main in username/project

? Title:  feat: Add user authentication with JWT
? Body:   <Received>
? What's next?  Submit
https://github.com/username/project/pull/47

PR Template

Her PR'da aynı yapıda bilgi istemek için template oluşturabilirsin:

# .github/PULL_REQUEST_TEMPLATE.md dosyası oluştur
mkdir -p .github
cat > .github/PULL_REQUEST_TEMPLATE.md << 'EOF'
## 📋 Açıklama
<!-- Bu PR ne yapıyor? Neden gerekli? -->

## 🔄 Değişiklik Türü
- [ ] 🐛 Bug fix
- [ ] ✨ Yeni özellik
- [ ] 💥 Breaking change
- [ ] 📝 Dokümantasyon
- [ ] 🎨 Stil/format
- [ ] ♻️ Refactoring
- [ ] ⚡ Performans

## 🧪 Test
- [ ] Mevcut testler geçiyor
- [ ] Yeni testler eklendi
- [ ] Manuel test yapıldı

## 📸 Ekran Görüntüsü (varsa)

## 🔗 İlgili Issue
<!-- Closes #issue_number -->

## ✅ Checklist
- [ ] Kod self-review yapıldı
- [ ] Yorum eklendi (gerekli yerlere)
- [ ] Dokümantasyon güncellendi
- [ ] Breaking change yok (varsa açıkla)
EOF

git add .github/PULL_REQUEST_TEMPLATE.md
git commit -m "Add PR template"

Bu template, her yeni PR açıldığında otomatik olarak açıklama alanında görünür. Ekip üyeleri doldurup gönderir.


Draft Pull Request

Bazen kodun henüz hazır değildir ama erken geri bildirim almak istersin. Ya da "üzerinde çalışıyorum" demek istersin. İşte bunun için Draft PR var.

Draft PR vs Normal PR

Normal PR:
  → "Kodum hazır, incelemeye alın"
  → Merge edilebilir
  → Reviewer'lar atanabilir

Draft PR:
  → "Henüz çalışıyorum, ama bakabilirsiniz"
  → Merge edilemez (butonu devre dışı)
  → Erken geri bildirim alabilirsin
  → Hazır olduğunda "Ready for review" yaparsın

Draft PR Oluşturma

# Web arayüzünde:
# "Create pull request" butonunun yanındaki oku tıkla
# → "Create draft pull request" seç

# GitHub CLI ile:
gh pr create --draft --title "WIP: Add payment integration"

Draft'tan Ready'ye Geçiş

# Web arayüzünde:
# PR sayfasında "Ready for review" butonuna tıkla

# GitHub CLI ile:
gh pr ready 47  # PR numarası

💡 İpucu: Draft PR'lar, büyük özellikleri parçalara ayırıp erken geri bildirim almak için harikadır. "90% bitti ama şu kısımda fikrinizi merak ediyorum" gibi durumlar için biçilmiş kaftan.


PR İnceleme Süreci

Bir PR açıldığında, reviewer'lar kodu inceler. İşte bu sürecin anatomisi:

Review Türleri

┌─────────────────────────────────────────────────────────┐
│                   PR REVIEW TÜRLERİ                     │
├─────────────────────────────────────────────────────────┤
│                                                         │
│  ✅ Approve                                             │
│     "Kod iyi görünüyor, merge edilebilir"              │
│                                                         │
│  💬 Comment                                             │
│     "Birkaç sorum/önerim var ama engel değil"          │
│                                                         │
│  ❌ Request Changes                                     │
│     "Bu değişiklikler yapılmadan merge edilemez"        │
│                                                         │
└─────────────────────────────────────────────────────────┘

Review Akışı

Developer        Reviewer           GitHub
    │                │                 │
    ├── PR oluştur ──┼────────────────►│
    │                │◄── bildirim ────┤
    │                │                 │
    │                ├── kodu incele ──►│
    │                ├── yorum yaz ───►│
    │                ├── değişiklik ──►│
    │                │   iste          │
    │◄── bildirim ───┤                 │
    │                │                 │
    ├── düzelt ──────┼────────────────►│
    ├── push et ─────┼────────────────►│
    │                │◄── bildirim ────┤
    │                │                 │
    │                ├── tekrar incele►│
    │                ├── onayla ──────►│
    │                │                 │
    ├── merge et ────┼────────────────►│
    │                │                 │

Satır Bazlı Yorum Yapma

PR'ın "Files changed" sekmesinde, herhangi bir satırın yanındaki + ikonuna tıklayarak o satıra özel yorum yazabilirsin:

// auth.js dosyasında değişiklik
+ function validateToken(token) {
+   const decoded = jwt.verify(token, SECRET_KEY);
+   return decoded;
+ }

Reviewer yorumu:

💬 @ahmet: Bu fonksiyon jwt.verify başarısız olursa hata fırlatır.
Try-catch ile sarmalaman lazım. Ayrıca SECRET_KEY'i environment
variable'dan al, hardcode etme.

Suggesting Changes

GitHub'ın çok güçlü bir özelliği: reviewer, direkt kod önerisi yapabilir ve PR sahibi tek tıkla uygulayabilir.

Yorumda suggestion bloğu kullanarak:

```suggestion
function validateToken(token) {
  try {
    const decoded = jwt.verify(token, process.env.JWT_SECRET);
    return { success: true, data: decoded };
  } catch (error) {
    return { success: false, error: error.message };
  }
}

PR sahibi **"Commit suggestion"** butonuna tıklayarak bu değişikliği doğrudan uygular. Manuel düzenleme gerekmez!

---

## Merge Stratejileri

PR onaylandıktan sonra merge zamanı gelir. GitHub üç farklı merge stratejisi sunar ve hangisini seçtiğin **projenin commit tarihçesini** doğrudan etkiler.

### 1. Create a Merge Commit (Varsayılan)

feature A───B───C / \ main ───X───────────M─── (M = merge commit)


- Tüm commit'ler olduğu gibi kalır
- Ekstra bir merge commit oluşur
- Branch'in tüm tarihçesi korunur
- `--no-ff` (no fast-forward) ile birleştirilir

```bash
# Terminal'de karşılığı:
git merge --no-ff feature/user-auth

Ne zaman kullanılır?

  • Her bir commit'in tarihçesini korumak istediğinde

  • Hangi commit'lerin hangi feature'a ait olduğunu görmek istediğinde

  • Büyük ve karmaşık projelerde

2. Squash and Merge

feature    A───B───C
          /
main  ───X───────────S─── (S = squash commit, A+B+C birleşti)
  • Feature branch'teki TÜM commit'ler tek bir commit'e sıkıştırılır

  • Ana branch'in tarihçesi temiz ve lineer kalır

  • Detaylı commit mesajları kaybolur (ama PR'da hâlâ görünür)

# Terminal'de karşılığı:
git merge --squash feature/user-auth
git commit -m "feat: Add user authentication (#47)"

Ne zaman kullanılır?

  • Feature branch'te çok fazla "WIP", "fix typo", "oops" commit'i varsa

  • Temiz, okunabilir bir main tarihçesi istiyorsan

  • Her PR'ın tek bir commit olarak görünmesini istiyorsan

3. Rebase and Merge

feature    A───B───C
          /
main  ───X───A'───B'───C'─── (commit'ler yeniden yazıldı, tekil dizildi)
  • Feature branch'teki commit'ler main'in ucuna yeniden uygulanır

  • Merge commit oluşmaz

  • Tamamen lineer bir tarihçe elde edersin

  • Commit hash'leri değişir (yeni commit'ler oluşur)

# Terminal'de karşılığı:
git rebase main feature/user-auth
git checkout main
git merge feature/user-auth  # fast-forward olur

Ne zaman kullanılır?

  • Her commit'in anlamlı ve atomik olduğu durumlarda

  • Çok temiz, lineer bir tarihçe istediğinde

  • Commit'lerin bağımsız olarak git bisect ile aranabilir olmasını istediğinde

Karşılaştırma Tablosu

┌─────────────────────┬──────────┬──────────┬──────────┐
│     Özellik         │  Merge   │  Squash  │  Rebase  │
├─────────────────────┼──────────┼──────────┼──────────┤
│ Commit korunur      │   ✅     │   ❌     │   ✅*    │
│ Merge commit        │   ✅     │   ❌     │   ❌     │
│ Lineer tarihçe      │   ❌     │   ✅     │   ✅     │
│ PR detayı görünür   │   ✅     │   ✅**   │   ✅     │
│ Kolay revert        │   ✅     │   ✅     │   ⚠️     │
│ Branch ilişkisi     │  Görünür │ Kaybolur │ Kaybolur │
│ Tarihçe karmaşıklığı│  Yüksek  │  Düşük   │  Düşük   │
└─────────────────────┴──────────┴──────────┴──────────┘

* Hash'ler değişir (yeni commit'ler oluşur)
** PR sayfasında orijinal commit'ler hâlâ görünür

Hangi Stratejiyi Seçmeli?

Açık kaynak proje (çok katkıcı)     → Squash and Merge
  Her katkıcının commit stili farklı, squash ile temizlenir

Kurumsal proje (düzenli ekip)       → Merge Commit veya Squash
  Merge commit: audit trail önemli
  Squash: temiz tarihçe tercih ediliyor

Kişisel proje (tek geliştirici)     → Rebase and Merge
  Commit'lerin zaten düzenli, lineer tarihçe güzel görünür

Çok büyük PR (50+ commit)           → Squash and Merge
  50 commit'i tarihçede görmek istemezsin

💡 İpucu: Bir repository'de Settings → General → Pull Requests altında hangi merge stratejilerinin kullanılabilir olacağını belirleyebilirsin. Örneğin, sadece "Squash and merge"e izin verip diğerlerini kapatabilirsin. Böylece tüm ekip aynı stratejiyi kullanmak zorunda kalır.


PR Yaşam Döngüsü

Bir PR'ın açılmasından kapanmasına kadar geçen süreçteki durumlar:

┌────────────┐
│   Open     │──── Review ──── Approve ──── Merge ──── Closed
│  (Açıldı)  │                                        (Merged)
└─────┬──────┘
      │
      ├──── Request Changes ──── Fix ──── Re-review ──── Approve ──── Merge
      │
      ├──── Conflict! ──── Resolve ──── Re-review
      │
      └──── Close without merge (Reddedildi / Vazgeçildi)

PR'ı Güncel Tutma

main branch ilerlerken senin PR'ın geride kalabilir. Conflict çıkabilir. Bunu çözmek için:

# Yöntem 1: main'i merge et (merge commit oluşur)
git checkout feature/user-auth
git fetch origin
git merge origin/main
# Conflict varsa çöz
git push

# Yöntem 2: main üzerine rebase et (temiz tarihçe)
git checkout feature/user-auth
git fetch origin
git rebase origin/main
# Conflict varsa çöz
git push --force-with-lease

⚠️ Dikkat: git push --force-with-lease kullanırken dikkatli ol. Bu komut remote'taki branch'i yeniden yazıyor. Eğer başka biri de aynı branch'e push ettiyse, onun değişiklikleri kaybolabilir. --force-with-lease en azından bu durumu kontrol eder ve uyarır.

GitHub'da da "Update branch" butonu var — bu, main'i PR branch'ine merge eder veya rebase eder (ayara göre).


PR ile İlgili GitHub CLI Komutları

# PR listele
gh pr list
gh pr list --state open
gh pr list --state closed
gh pr list --state merged

# PR detayını görüntüle
gh pr view 47
gh pr view 47 --web  # Tarayıcıda aç

# PR'ı kontrol et (branch'e geç)
gh pr checkout 47

# PR'daki değişiklikleri gör
gh pr diff 47

# PR'ı onayla
gh pr review 47 --approve --body "LGTM! 🚀"

# PR'a değişiklik iste
gh pr review 47 --request-changes --body "Lütfen hata yönetimini ekle"

# PR'ı merge et
gh pr merge 47 --merge    # merge commit ile
gh pr merge 47 --squash   # squash ile
gh pr merge 47 --rebase   # rebase ile

# Merge sonrası branch'i sil
gh pr merge 47 --squash --delete-branch

# PR'ı kapat (merge etmeden)
gh pr close 47

Linked Issues — PR ve Issue Bağlantısı

PR'ı bir issue ile ilişkilendirebilirsin. Böylece PR merge edildiğinde issue otomatik olarak kapanır:

# PR açıklamasında şu anahtar kelimeleri kullan:

Closes #42
Fixes #42
Resolves #42

# Birden fazla issue kapatmak için:
Closes #42, closes #43, closes #44

# Farklı repo'daki issue:
Closes username/other-repo#42
Issue #42: "Login sayfası çalışmıyor"
     │
     ├── PR #47: "feat: Fix login page"
     │           Description: "Closes #42"
     │
     └── PR #47 merge edildiğinde
         → Issue #42 otomatik kapanır ✅

PR Best Practices

İyi Bir PR Nasıl Olmalı?

1. KÜÇÜK TUTUN
   ❌ 50 dosya, 3000 satır değişiklik
   ✅ 5-10 dosya, 200-400 satır değişiklik
   
   Neden? Büyük PR'lar:
   - İncelenmesi zor
   - Hata kaçırma olasılığı yüksek
   - Conflict olasılığı yüksek
   - "LGTM" (Looks Good To Me) deyip geçilir

2. TEK SORUMLULUK
   ❌ Auth + Database migration + CSS fix hepsi bir PR'da
   ✅ Her PR tek bir şey yapar

3. AÇIKLAYICI BAŞLIK
   ❌ "Fix stuff"
   ❌ "Update code"
   ✅ "feat: Add JWT authentication to API endpoints"
   ✅ "fix: Resolve login redirect loop on expired tokens"

4. BAĞLAM VER
   - Neden bu değişiklik gerekli?
   - Ne değişti? (özet)
   - Nasıl test edildi?
   - Ekran görüntüsü (UI değişikliği varsa)
   - İlgili issue numarası

5. SELF-REVIEW YAP
   PR'ı açmadan önce kendi kodunu bir kez incele.
   Typo'lar, debug log'ları, gereksiz dosyalar...

PR Boyutu ve İnceleme Kalitesi

Satır Sayısı    İnceleme Kalitesi    Tahmini Süre
─────────────   ─────────────────    ────────────
1-50            ⭐⭐⭐⭐⭐ Mükemmel      5-10 dk
50-200          ⭐⭐⭐⭐ İyi            15-30 dk
200-500         ⭐⭐⭐ Orta             30-60 dk
500-1000        ⭐⭐ Zayıf             1-2 saat
1000+           ⭐ "LGTM" 😅          Kimse okumaz

💡 İpucu: Google'ın iç araştırmasına göre, 200 satırdan küçük PR'lar en yüksek kalitede incelenir. "Küçük PR, hızlı merge" — bu altın kuralı unutma.


Auto-merge ve Merge Queue

Auto-merge

Tüm kontroller (CI testleri, review onayı) geçtiğinde PR'ın otomatik merge edilmesini sağlayabilirsin:

# GitHub CLI ile auto-merge etkinleştir
gh pr merge 47 --auto --squash

# Web arayüzünde:
# PR sayfasında "Enable auto-merge" butonuna tıkla

Bu özelliğin çalışması için:

  • Repository ayarlarında auto-merge etkin olmalı

  • Branch protection rules tanımlı olmalı

  • Gerekli tüm kontroller (CI, review) geçmeli

Merge Queue (Birleştirme Kuyruğu)

Büyük ekiplerde birçok PR aynı anda merge edilmek ister. Merge queue, PR'ları sıraya alır ve her birini sırayla test edip merge eder:

PR #47 ──┐
PR #48 ──┼── Merge Queue ── Test → Merge → Test → Merge → ...
PR #49 ──┘

Bu, "main branch her zaman yeşil (çalışır durumda) kalsın" ilkesini garanti eder.


Yaygın PR Hataları

1. Dev PR Açmak

# ❌ 3 haftadır tek branch'te çalışıyorsun, 80 dosya değişti
# Reviewer: "Bu PR çok büyük, parçalara ayırır mısın?"

# ✅ Büyük feature'ları küçük, bağımsız PR'lara böl:
# PR #1: Database schema değişiklikleri
# PR #2: API endpoint'leri
# PR #3: Frontend entegrasyonu
# PR #4: Testler

2. Force Push ile Review Kaybetme

# ❌ Reviewer yorum yapmış, sen force push ile commit'leri yeniden yazdın
# Reviewer'ın yorumları artık hangi koda ait belli değil!

# ✅ Review sürecinde force push yerine yeni commit ekle
# Merge sırasında squash kullanarak temizle

3. Conflict'i Çözmeden Beklemek

# ❌ "Conflict var ama birisi çözer" diye beklemek
# Zaman geçtikce conflict büyür!

# ✅ Conflict çıktığında hemen çöz
git fetch origin
git merge origin/main
# veya
git rebase origin/main

Pratik Senaryo: Tam Bir PR Akışı

# 1. Güncel main'den başla
git checkout main
git pull origin main

# 2. Feature branch oluştur
git checkout -b feature/dark-mode

# 3. Kod yaz
cat > src/theme.js << 'EOF'
export const themes = {
  light: {
    background: '#ffffff',
    text: '#000000',
    primary: '#007bff'
  },
  dark: {
    background: '#1a1a2e',
    text: '#e0e0e0',
    primary: '#4dabf7'
  }
};

export function applyTheme(themeName) {
  const theme = themes[themeName];
  if (!theme) throw new Error(`Unknown theme: ${themeName}`);
  
  Object.entries(theme).forEach(([key, value]) => {
    document.documentElement.style.setProperty(`--${key}`, value);
  });
}
EOF

# 4. Test yaz
cat > tests/theme.test.js << 'EOF'
import { themes, applyTheme } from '../src/theme';

test('should have light and dark themes', () => {
  expect(themes.light).toBeDefined();
  expect(themes.dark).toBeDefined();
});

test('should throw for unknown theme', () => {
  expect(() => applyTheme('neon')).toThrow('Unknown theme: neon');
});
EOF

# 5. Commit ve push
git add .
git commit -m "feat: add dark mode theme support"
git push -u origin feature/dark-mode

# 6. PR oluştur
gh pr create \
  --title "feat: Add dark mode theme support" \
  --body "## Açıklama
Dark mode desteği eklendi. Kullanıcılar light/dark tema seçebilir.

## Test
- [x] Unit testler eklendi
- [x] Manuel test yapıldı

Closes #15" \
  --reviewer senior-dev \
  --label "feature,ui"

# 7. Review sonrası düzeltme gerekirse
# ... düzelt, commit et, push et
git add .
git commit -m "fix: handle theme persistence in localStorage"
git push

# 8. Onay gelince merge et
gh pr merge --squash --delete-branch

Özet

Bu derste Pull Request'in tüm detaylarını öğrendik:

  • Pull Request, bir branch'teki değişiklikleri ana branch'e alma isteğidir — ekip işbirliğinin temelidir

  • Draft PR, henüz hazır olmayan ama erken geri bildirim almak istediğin değişiklikler için kullanılır

  • PR Template ile ekipteki herkes aynı yapıda PR açar — tutarlılık sağlanır

  • Üç merge stratejisi var: Merge commit (tarihçe korunur), Squash (tek commit'e sıkışır), Rebase (lineer tarihçe) — projenin ihtiyacına göre seç

  • Küçük PR'lar daha hızlı ve kaliteli incelenir — 200 satır altı ideal

  • Linked Issues ile PR merge edildiğinde ilgili issue otomatik kapanır (Closes #42)

  • Auto-merge ve Merge Queue ile CI/CD süreçleriyle entegre, otomatik birleştirme yapılabilir

Bir sonraki derste GitHub'ın proje yönetim araçlarını göreceğiz: Issues, Labels, Milestones ve Projects.