GitHub Pull Request Süreci ve Code Review En İyi Uygulamaları
Ekibimizde bir dönem pull request sürecini neredeyse hiç kullanmıyorduk. Herkes doğrudan main branch’e push ediyordu, kod review diye bir şey yoktu ve her deployment bir kumar gibiydi. Sonra bir gün production’da tam anlamıyla bir felaket yaşadık; birinin yarım kalan bir migration’ı merge etmesiyle veritabanı şeması bozuldu. O günden sonra PR sürecini ciddiye almaya başladık. Bu yazıda hem teorik hem de sahadan öğrendiğim pratik bilgilerle GitHub Pull Request ve Code Review sürecini ele alacağım.
Pull Request Nedir ve Neden Bu Kadar Önemli
Pull Request, özünde bir kod değişikliğini ana branch’e dahil etmeden önce ekiple paylaşma mekanizmasıdır. Ama bunu sadece “onay alma süreci” olarak düşünmek büyük hata. PR süreci aynı zamanda:
- Bilgi paylaşımının gerçekleştiği bir platform
- Potansiyel hataların canlıya çıkmadan yakalandığı bir filtre
- Ekip içi standartların oturmasını sağlayan bir araç
- Yeni ekip üyelerinin kod tabanını öğrendiği bir okul
Küçük ekiplerde “biz zaten konuşuyoruz, PR’a ne gerek var” diye düşünülebilir. Bu düşünce çok tehlikeli. Sözlü iletişim kaybolur; PR yorumları kayıt altında kalır ve ileride referans alınabilir.
Branch Stratejisi Olmadan PR Süreci Olmaz
PR sürecine geçmeden önce branch stratejinizi netleştirmeniz gerekiyor. En yaygın yaklaşımları şöyle sıralayabilirim:
- Feature Branch Workflow: Her yeni özellik veya bug fix için ayrı branch açılır
- Gitflow:
develop,release,hotfixgibi özel amaçlı branch’ler kullanılır - Trunk-Based Development: Kısa ömürlü branch’ler, sık merge
Biz genellikle feature branch + trunk-based arası bir hibrit kullanıyoruz. Branch isimlendirmesi de önemli; tutarsız isimler zamanla karmaşaya yol açar.
# Önerilen branch isimlendirme formatları
git checkout -b feature/user-authentication
git checkout -b bugfix/login-redirect-loop
git checkout -b hotfix/payment-null-pointer
git checkout -b chore/update-dependencies
git checkout -b docs/api-documentation
# Branch listesini görmek
git branch -a
# Uzak branch'leri temizlemek (merged olanları sil)
git fetch --prune
git branch -r | grep -v '->' | grep -v main | xargs -I {} git branch -d {}
Branch ismindeki feature/, bugfix/, hotfix/ prefiksleri hem insanlar hem de CI/CD araçları için kolaylık sağlar. Örneğin hotfix branch’lerini tespit eden pipeline’lar farklı deployment kuralları uygulayabilir.
İlk PR’ı Açmadan Önce
Bir PR açmadan önce yapılması gereken birkaç kritik adım var. Bunları atlamak hem size hem de reviewer’a zaman kaybettirir.
# Main branch'teki son değişiklikleri al
git checkout main
git pull origin main
# Feature branch'ini main ile rebase et
git checkout feature/user-authentication
git rebase main
# Olası conflict'leri çöz ve devam et
git add .
git rebase --continue
# Değişiklikleri push et
git push origin feature/user-authentication --force-with-lease
--force-with-lease bayrağına dikkat edin. Normal --force yerine bunu kullanmak çok önemli. --force siz push etmeden başkası branch’e bir şey yazmışsa onu ezer. --force-with-lease ise “remote’daki son commit benim bildiğimle aynıysa push et, değilse reddet” demek. Production’da birinin çalışmasını ezdiğimiz için yaşadığım tartışmaları hatırlamak istemiyorum.
PR açmadan önce kendi değişikliklerinizi bir kez daha gözden geçirin:
# Main'den bu yana yapılan tüm değişiklikleri gör
git diff main..HEAD
# Sadece değişen dosyaların listesi
git diff main..HEAD --name-only
# Commit geçmişi
git log main..HEAD --oneline
PR Açma: Başlık ve Açıklama
GitHub’da PR açarken en çok ihmal edilen şey açıklama kısmı. “Added user auth” gibi tek satır bir açıklama bırakan PR’ları görünce içim sıkışıyor. İyi bir PR açıklaması şunları içermeli:
- Ne yaptım?
- Neden yaptım? (hangi ihtiyacı karşılıyor)
- Nasıl test ettim?
- Reviewer’ın özellikle dikkat etmesini istediğim yer var mı?
- Ekran görüntüsü veya video (UI değişikliği varsa)
Bunun için bir PR template kullanmanızı tavsiye ederim. Projenizdeki .github/PULL_REQUEST_TEMPLATE.md dosyası bunu otomatik hale getirir:
# .github/PULL_REQUEST_TEMPLATE.md oluştur
mkdir -p .github
cat > .github/PULL_REQUEST_TEMPLATE.md << 'EOF'
## Ne Değiştirdim
<!-- Yapılan değişiklikleri kısaca açıkla -->
## Neden Değiştirdim
<!-- Bu değişikliğin motivasyonu, ilgili issue varsa bağla -->
Closes #
## Test Adımları
<!-- Reviewer bu değişikliği nasıl test edebilir? -->
1.
2.
## Kontrol Listesi
- [ ] Testler yazıldı
- [ ] Dokümantasyon güncellendi
- [ ] Lint hataları giderildi
- [ ] Breaking change yok (varsa açıkla)
## Ekran Görüntüsü (varsa)
EOF
Bu template her yeni PR açıldığında otomatik olarak açıklama alanına gelir.
Code Review: Reviewer Perspektifinden
Code review en çok yanlış anlaşılan süreçlerden biri. Pek çok ekipte reviewer olmanın görevi “hatayı bul ve yorum bırak” şeklinde algılanıyor. Halbuki review süreci çok daha nüanslı.
İyi bir reviewer şunlara bakar:
- Mantık hataları ve edge case’ler
- Performans sorunları (gereksiz N+1 sorguları, bellek sızıntıları)
- Güvenlik açıkları (SQL injection, XSS, credential exposure)
- Kod okunabilirliği
- Test coverage
- Standartlara uyum
Yorumlarınızın tonu da en az içeriği kadar önemli. “Bu yanlış” yerine “Burada X durumunda Y problemi yaşanabilir, Z yaklaşımı daha güvenli olabilir” demek hem daha yapıcı hem de motivasyonu kırmaz.
GitHub’ın review arayüzü birkaç önemli seçenek sunuyor:
- Comment: Görüş belirtir ama approve/request changes içermez
- Approve: Değişiklikleri onaylar
- Request Changes: Reviewer belirtilen sorunlar çözülmeden merge edilmesini istemez
“Request Changes” kullanırken ne istediğinizi çok net belirtin. “Bu kısım daha iyi yazılabilir” yeterli değil. “Bu kısımda getUserById çağrısı her loop iterasyonunda yapılıyor, bunu döngü dışına al veya bulk çekimi düşün” şeklinde olmalı.
Branch Protection Rules
PR sürecini zorunlu kılmak için branch protection kurallarını aktive etmeniz gerekiyor. Bu olmadan herkes istediği zaman main’e push edebilir.
GitHub repository settings üzerinden yapabileceğiniz şeyleri CLI üzerinden de yönetebilirsiniz. GitHub CLI (gh) kullanıyorsanız:
# GitHub CLI kurulumu
# Ubuntu/Debian
curl -fsSL https://cli.github.com/packages/githubcli-archive-keyring.gpg | sudo dd of=/usr/share/keyrings/githubcli-archive-keyring.gpg
echo "deb [arch=$(dpkg --print-architecture) signed-by=/usr/share/keyrings/githubcli-archive-keyring.gpg] https://cli.github.com/packages stable main" | sudo tee /etc/apt/sources.list.d/github-cli.list > /dev/null
sudo apt update && sudo apt install gh
# GitHub'a login ol
gh auth login
# PR listesi
gh pr list
# PR detayı
gh pr view 42
# PR'ı terminal üzerinden onayla
gh pr review 42 --approve
# PR'ı merge et
gh pr merge 42 --squash --delete-branch
Branch protection ayarları için GitHub API’yi kullanabilirsiniz:
# Branch protection rule ekle (curl ile GitHub API)
curl -X PUT
-H "Authorization: token YOUR_TOKEN"
-H "Accept: application/vnd.github.v3+json"
https://api.github.com/repos/OWNER/REPO/branches/main/protection
-d '{
"required_status_checks": {
"strict": true,
"contexts": ["ci/tests", "ci/lint"]
},
"enforce_admins": true,
"required_pull_request_reviews": {
"required_approving_review_count": 2,
"dismiss_stale_reviews": true
},
"restrictions": null
}'
Bu ayarlarla:
- En az 2 onay olmadan merge edilemiyor
- CI testleri geçmeden merge edilemiyor
- Yeni commit gelince eski onaylar geçersiz sayılıyor
- Admin’ler bile direkt push yapamıyor
CODEOWNERS Dosyası
Büyük projelerde her PR için tüm ekibi reviewer olarak atamak saçmalığa dönüşür. CODEOWNERS dosyası, hangi dosya veya dizinlerin hangi kişi ya da ekip tarafından review edilmesi gerektiğini tanımlar.
# .github/CODEOWNERS dosyası oluştur
cat > .github/CODEOWNERS << 'EOF'
# Genel sahiplik - her şey için bu ekip review eder
* @ornek-sirket/backend-team
# Veritabanı migration'ları için DBA onayı zorunlu
/db/migrations/ @ornek-sirket/dba-team
# Frontend dosyaları
/frontend/ @ornek-sirket/frontend-team
*.css @ornek-sirket/frontend-team
*.tsx @ornek-sirket/frontend-team
# DevOps konfigürasyonları
/.github/ @ornek-sirket/devops-team
/kubernetes/ @ornek-sirket/devops-team
Dockerfile @ornek-sirket/devops-team
docker-compose*.yml @ornek-sirket/devops-team
# Güvenlik kritik dosyalar
/auth/ @kullanici-adi-1 @kullanici-adi-2
/security/ @kullanici-adi-1
EOF
CODEOWNERS sayesinde bir migration dosyası değiştiğinde DBA ekibinin otomatik olarak reviewer olarak atanması sağlanır. Güvenlik ekibi auth klasörüne dokunan her PR’dan otomatik haberdar olur. Bu “beni kaçırmışlar” sorununu büyük ölçüde çözer.
GitHub Actions ile PR Otomasyonu
PR sürecini sadece insan review’ına bırakmak yetersiz. Otomatik kontroller hem reviewer’ın yükünü hafifletir hem de hataları erkenden yakalar.
# .github/workflows/pr-checks.yml
name: PR Checks
on:
pull_request:
branches: [ main, develop ]
jobs:
lint:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- name: Python lint
run: |
pip install flake8 black
flake8 . --max-line-length=100
black --check .
test:
runs-on: ubuntu-latest
needs: lint
steps:
- uses: actions/checkout@v4
- name: Run tests
run: |
pip install -r requirements.txt
pytest --cov=./src --cov-report=xml
- name: Coverage check
run: |
coverage_percent=$(python -c "
import xml.etree.ElementTree as ET
tree = ET.parse('coverage.xml')
root = tree.getroot()
print(float(root.attrib['line-rate']) * 100)
")
echo "Coverage: $coverage_percent%"
if (( $(echo "$coverage_percent < 80" | bc -l) )); then
echo "Coverage %80'in altında!"
exit 1
fi
security-scan:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- name: Secret scanning
run: |
pip install detect-secrets
detect-secrets scan --baseline .secrets.baseline
detect-secrets audit .secrets.baseline
Bu workflow PR açıldığında otomatik olarak lint, test ve güvenlik taraması yapar. Test coverage %80’in altına düşerse PR otomatik başarısız sayılır. Reviewer artık “testler var mı, lint geçiyor mu” diye elle kontrol etmek zorunda kalmaz.
Squash, Merge ve Rebase: Doğru Seçimi Yapmak
PR merge edilirken üç strateji arasında seçim yapmanız gerekiyor. Her birinin artıları ve eksileri var.
# Squash merge - tüm commit'leri tek commit'e sıkıştırır
gh pr merge 42 --squash
# Regular merge - merge commit oluşturur
gh pr merge 42 --merge
# Rebase merge - doğrusal geçmiş oluşturur
gh pr merge 42 --rebase
# Local olarak squash nasıl yapılır
git checkout main
git merge --squash feature/user-authentication
git commit -m "feat: kullanicı kimlik doğrulama sistemi eklendi (#42)"
Benim önerim:
- Squash merge: Feature branch’ler için ideal. PR içindeki “WIP: deniyorum”, “lint düzelttim” gibi gürültülü commit’ler tek temiz bir commit’e dönüşür
- Rebase merge: Temiz doğrusal geçmiş isteniyorsa, her commit’in anlamlı olduğu projelerde
- Regular merge: Merge geçmişinin korunmasının önemli olduğu uzun yaşayan branch’lerde
Draft PR Kullanımı
Draft PR, review almaya hazır olmayan ama ekibe “bu konuda çalışıyorum” mesajı vermek istediğinizde kullanılır. Yanlış anlaşılmasın, bu “yarım iş paylaşma” değil, “erken geri bildirim alma” mekanizması.
# Draft PR oluştur
gh pr create --draft --title "WIP: Ödeme sistemi entegrasyonu" --body "İlk implementasyon, henüz review için hazır değil"
# Draft'tan ready'e geçir
gh pr ready 43
Draft PR kullanmanın pratik faydaları:
- CI pipeline’ı erken başlatırsınız
- Ekip ne üzerinde çalıştığınızı bilir
- Kısmi feedback almak istediğinizde “sadece mimari yapıya bakabilir misin” diyebilirsiniz
- “Merge edilmeden önce” baskısı olmadan rahat geliştirme yaparsınız
Konflikt Yönetimi
Uzun süre açık kalan PR’larda kaçınılmaz olarak conflict çıkar. Conflict çözümünü reviewer’ı bekletmeden yapın.
# Remote değişiklikleri çek
git fetch origin
# Interactive rebase ile conflict'leri çöz
git rebase origin/main
# Conflict olan dosyaları gör
git status
# Conflict'i düzenle
# <<<<<<< HEAD
# sizin kodunuz
# =======
# main'deki kod
# >>>>>>> origin/main
# yukarıdaki işaretleri kaldırarak doğru kodu bırak
git add conflicted-file.py
git rebase --continue
# Zorla push (force-with-lease ile)
git push origin feature/user-authentication --force-with-lease
Conflict çözümü sırasında emin olmadığınız bir yerde git blame ile o satırı kimin yazdığına ve commit mesajına bakın. Sonra kararı tek başınıza vermeye çalışmak yerine o kişiyle konuşun.
Büyük PR’lardan Kaçının
Sahada en çok yapılan hatalardan biri büyük PR’lar açmak. 2000 satır değişiklik içeren bir PR’ı düzgün review etmek neredeyse imkansız. Reviewer yorulur, gözden kaçırmalar artar.
İdeal PR büyüklüğü hakkında katı kurallar olmasa da 400 satırın altını hedefleyin. Bunu sağlamak için:
- Bir feature’ı alt parçalara bölün
- Her parçayı bağımsız PR olarak açın
- PR’lar arasında bağımlılık varsa açıklayın
- Refactoring’i ayrı PR’a alın
Büyük bir değişiklik kaçınılmazsa PR açıklamasında “önce şu dosyalara bakın, sonra bu sırayla ilerleyin” gibi review rehberi ekleyin.
Sonuç
Pull Request süreci sadece bir araç değil, ekip kültürünün yansıması. İyi işleyen bir PR süreci için teknik araçlar kadar davranışsal alışkanlıklar da önemli. PR yorumlarınızın tonu, review hızınız, açıkladığınız PR’ların kalitesi ve conflict anlarındaki tutumunuz zamanla ekip normlarını şekillendirir.
Başlangıç için küçük adımlarla başlayın:
- Branch protection rule’ları aktive edin
- PR template oluşturun
- Temel bir CI pipeline kurun
- CODEOWNERS dosyası yazın
Bu dört adımı attıktan sonra sürecin nasıl olgunlaştığını kendiniz göreceksiniz. Ekip büyüdükçe veya kod tabanı karmaşıklaştıkça kuralları gözden geçirin ve revize edin. Benim tecrübeme göre iyi bir PR kültürü, production incident sayısını gözle görülür biçimde azaltıyor ve “bu kodu kim yazdı ki böyle” sorularını da.
