Code Review
Giriş — Dört Göz İki Gözden İyidir
Kodunu yazdın, testlerini çalıştırdın, her şey güzel çalışıyor. PR'ını açtın. Ama merge butonuna basmadan önce bir adım daha var: başka birinin kodunu incelemesi.
Neden? Çünkü kendi kodundaki hataları görmek çok zordur. Bir mektup yazdığında kendi yazım hatalarını fark edemezsin — ama başkası okursa hemen yakalar. Kod da öyle. "Bu çalışıyor" ile "Bu iyi yazılmış" arasında büyük fark var.
Code review, sadece hata bulmak değildir. Bilgi paylaşımı, ekip standartlarının korunması ve junior geliştiricilerin yetiştirilmesi için de kritik bir süreçtir.
Code Review Nedir ve Neden Önemlidir?
Analoji — Bir Binanın İnşaat Denetimi
Bir bina inşa ediliyor. Mühendis planı çizdi, işçiler duvarları ördü. Ama binayı insanlara açmadan önce bir yapı denetçisi gelir. Duvarların sağlamlığını, elektrik tesisatının güvenliğini, yangın çıkışlarının varlığını kontrol eder.
Denetçi her şeyi yıkıp yeniden yapmaz. Sorunları işaret eder, önerilerde bulunur, standartlara uygunluğu doğrular. Amacı binayı daha güvenli ve yaşanabilir yapmaktır.
Code review tam olarak bu denetim sürecidir:
Mühendis (Mimar) → Developer (PR sahibi)
İnşaat → Kod değişiklikleri
Yapı denetçisi → Reviewer
Denetim raporu → Review yorumları
Oturma izni → Approval + mergeCode Review'ın Faydaları
┌─────────────────────────────────────────────────────────────┐
│ CODE REVIEW'IN 6 BÜYÜK FAYDASI │
├─────────────────────────────────────────────────────────────┤
│ │
│ 1. 🐛 Hata Yakalama │
│ Testlerin yakalamadığı mantık hatalarını bulur │
│ Edge case'ler, off-by-one, null pointer... │
│ │
│ 2. 📚 Bilgi Paylaşımı │
│ "Bu kütüphanenin daha kolay yolu var" gibi öneriler │
│ Herkes projenin her yerini tanır │
│ │
│ 3. 📏 Kod Standartları │
│ Tutarlı naming convention, mimari pattern'ler │
│ "Bu projede Promise yerine async/await kullanıyoruz" │
│ │
│ 4. 🎓 Mentorluk │
│ Junior geliştiriciler, senior'ların review'larından │
│ öğrenir. En etkili öğrenme yöntemlerinden biri. │
│ │
│ 5. 🔒 Güvenlik │
│ SQL injection, XSS, hardcoded secrets... │
│ İkinci bir çift göz güvenlik açıklarını yakalar │
│ │
│ 6. 👥 Ekip Sahipliği │
│ "Bu kodu sadece Ahmet biliyor" sorununu önler │
│ Bus factor artar (birisi ayrılsa proje devam eder) │
│ │
└─────────────────────────────────────────────────────────────┘💡 İpucu: Google'ın araştırmasına göre, production bug'larının %60'ından fazlası code review ile yakalanabilir. Microsoft'ta ise her review edilen 1000 satır kodda ortalama 15 defect bulunuyor.
Review Süreci — Adım Adım
1. PR İncelemeye Hazır mı?
Review'a başlamadan önce kontrol et:
☑ PR açıklaması yeterli mi? (Ne değişti, neden?)
☑ PR boyutu makul mü? (200-400 satır ideal)
☑ CI testleri geçiyor mu? (❌ failing testlerle review yapma)
☑ Conflict var mı? (Conflict'li PR review edilmez)
☑ Draft mı yoksa Ready mı? (Draft ise detaylı review bekleme)2. Büyük Resimden Başla
Satır satır koda girmeden önce büyük resmi anla:
1. PR açıklamasını oku — Ne yapılmak isteniyor?
2. Dosya listesine bak — Hangi dosyalar değişmiş?
3. Commit tarihçesini gözden geçir — Mantıklı bir akış var mı?
4. Mimari uygunluğu değerlendir — Proje yapısına uyuyor mu?3. Detaylı İnceleme
Kontrol Listesi:
─────────────────────────────────────────
✅ Doğruluk → Kod beklenen işi yapıyor mu?
✅ Okunabilirlik → Başkası anlayabilir mi?
✅ Basitlik → Daha basit bir yol var mı?
✅ Güvenlik → Güvenlik açığı var mı?
✅ Performans → Gereksiz işlem, N+1 sorgusu var mı?
✅ Test → Yeterli test yazılmış mı?
✅ Error handling→ Hatalar düzgün yönetiliyor mu?
✅ Naming → Değişken/fonksiyon adları anlaşılır mı?
✅ Dokümantasyon → Gerekli yorum/docstring eklenmiş mi?
✅ Edge cases → Sınır durumları düşünülmüş mü?4. Geri Bildirim Ver
Review sonuçlarını üç şekilde iletebilirsin:
✅ Approve (Onayla)
"Kod iyi görünüyor, merge edilebilir"
💬 Comment (Yorum)
"Birkaç küçük önerim var ama engel değil"
❌ Request Changes (Değişiklik İste)
"Bu sorunlar çözülmeden merge edilmemeli"Yorum Türleri ve Kısaltmalar
Profesyonel ekiplerde review yorumlarında belirli önekler kullanılır. Bu, yorumun ciddiyetini ve niyetini netleştirir:
Yorum Önekleri
[nit] → Nitpick. Çok küçük, kozmetik. Bloklamaz.
"nit: burada tek tırnak yerine çift tırnak kullanmışsın"
[suggestion]→ Öneri. Kabul etme zorunluluğu yok.
"suggestion: bu fonksiyonu böyle de yazabilirsin"
[question] → Soru. Anlamak için soruluyor.
"question: burada neden Map yerine Object kullandın?"
[todo] → Şimdi değil ama ileride yapılmalı.
"todo: bunu bir sonraki PR'da refactor edebilirsin"
[blocking] → Engelleyici. Bu düzeltilmeden merge edilmemeli.
"blocking: bu SQL injection'a açık, parametrize et"
[praise] → Övgü. İyi yapılmış bir şeyi belirt.
"praise: bu abstraction çok temiz olmuş! 👏"Gerçek Dünya Review Örnekleri
// PR'da eklenen kod:
+ function getUser(id) {
+ const user = db.query(`SELECT * FROM users WHERE id = ${id}`);
+ return user;
+ }Reviewer yorumları:
🔴 [blocking] SQL Injection açığı var! Kullanıcı input'u doğrudan
SQL sorgusuna eklenmemeli. Parametrize sorgu kullan:
```suggestion
function getUser(id) {
const user = db.query('SELECT * FROM users WHERE id = $1', [id]);
return user;
}+ function calculateTax(price) {
+ return price * 0.18;
+ }💬 [suggestion] Magic number yerine sabit kullanmak daha okunabilir:
```suggestion
const TAX_RATE = 0.18;
function calculateTax(price) {
return price * TAX_RATE;
}+ async function fetchUserData(userId) {
+ try {
+ const response = await api.get(`/users/${userId}`);
+ const orders = await api.get(`/users/${userId}/orders`);
+ const reviews = await api.get(`/users/${userId}/reviews`);
+ return { ...response.data, orders: orders.data, reviews: reviews.data };
+ } catch (error) {
+ console.log(error);
+ }
+ }💬 [suggestion] Üç bağımsız API çağrısı sıralı yapılmış.
Promise.all ile paralel yapabilirsin, 3x hızlanır:
```suggestion
async function fetchUserData(userId) {
try {
const [user, orders, reviews] = await Promise.all([
api.get(`/users/${userId}`),
api.get(`/users/${userId}/orders`),
api.get(`/users/${userId}/reviews`),
]);
return { ...user.data, orders: orders.data, reviews: reviews.data };
} catch (error) {
logger.error('Failed to fetch user data', { userId, error });
throw error; // Hatayı yut, yukarı fırlat
}
}⚠️ Ayrıca console.log(error) yerine düzgün bir logger kullan ve hatayı yutma — yukarı fırlat ki çağıran kod da haberdar olsun.
---
## Suggesting Changes — Kod Önerisi
GitHub'ın en güçlü review özelliklerinden biri: reviewer, doğrudan kod önerisi yapabilir ve PR sahibi **tek tıkla** uygulayabilir.
### Suggestion Nasıl Yapılır?
PR'ın "Files changed" sekmesinde, bir satıra yorum yaparken suggestion bloğu kullan:
````markdown
Fonksiyon adı daha açıklayıcı olabilir:
```suggestion
function calculateMonthlyPayment(principal, rate, months) {
### Çoklu Satır Suggestion
Birden fazla satırı seçip tek bir suggestion yapabilirsin:
İlk satırın yanındaki + ikonuna tıkla
Son satıra kadar sürükle (birden fazla satır seçilir)
Suggestion bloğunda yeni kodu yaz
### Batch Commit
PR sahibi birden fazla suggestion'ı tek bir commit'te uygulayabilir:
Her suggestion'da "Add suggestion to batch" tıkla
Tüm istediğin suggestion'ları batch'e ekle
"Commit suggestions" ile hepsini tek commit'te uygula
Bu, review sonrası "apply review suggestions" gibi temiz bir commit mesajı üretir.
> 💡 **İpucu:** Suggestion özelliği sadece eklenen veya değiştirilen satırlarda çalışır. Silinen satırlarda veya değişmeyen dosyalarda suggestion yapamazsın.
---
## CODEOWNERS — Kod Sahipliği
CODEOWNERS dosyası, hangi dosya veya dizinlerin kimin "sahipliğinde" olduğunu tanımlar. Bu dosyada belirtilen kişiler, ilgili dosyalar değiştiğinde otomatik olarak PR'a reviewer olarak eklenir.
### CODEOWNERS Dosyası Oluşturma
```bash
# .github/CODEOWNERS dosyası oluştur
cat > .github/CODEOWNERS << 'EOF'
# CODEOWNERS — Kod Sahipliği Dosyası
# Her satır: dosya-pattern sahip-kişi/takım
# Varsayılan sahipler (her dosya için)
* @tech-lead
# Frontend
/src/components/ @frontend-team
/src/pages/ @frontend-team
/src/styles/ @design-team
*.css @design-team
*.scss @design-team
# Backend
/src/api/ @backend-team
/src/services/ @backend-team
/src/models/ @backend-team @database-admin
# DevOps
/.github/workflows/ @devops-team
Dockerfile @devops-team
docker-compose.yml @devops-team
*.tf @devops-team
# Dokümantasyon
/docs/ @tech-writer
*.md @tech-writer @tech-lead
# Güvenlik kritik dosyalar
/src/auth/ @security-team @tech-lead
/src/middleware/auth* @security-team
# Yapılandırma dosyaları
package.json @tech-lead
tsconfig.json @tech-lead
.eslintrc* @tech-lead
EOF
git add .github/CODEOWNERS
git commit -m "Add CODEOWNERS file"CODEOWNERS Nasıl Çalışır?
Developer, /src/components/Button.jsx dosyasını değiştirip PR açtı.
CODEOWNERS dosyasına göre:
/src/components/ → @frontend-team
Sonuç:
@frontend-team otomatik olarak reviewer olarak eklenir.
Branch protection "Require review from Code Owners" açıksa:
@frontend-team onaylamadan merge edilemez!┌─────────────────────────────────────────────────────────┐
│ PR #52: "Fix Button hover state" │
│ │
│ Files Changed: │
│ src/components/Button.jsx │
│ src/styles/button.css │
│ │
│ Auto-assigned Reviewers (from CODEOWNERS): │
│ ✅ @frontend-team (components/) │
│ ⏳ @design-team (*.css) │
│ │
│ Status: Waiting for review from code owners │
└─────────────────────────────────────────────────────────┘CODEOWNERS Pattern Sözdizimi
# Tüm dosyalar
* @default-owner
# Belirli dosya uzantısı
*.js @js-team
*.py @python-team
# Belirli dizin (ve alt dizinleri)
/docs/ @docs-team
# Belirli dosya
/src/config/database.yml @dba-team
# Glob pattern
/src/**/test_*.py @qa-team
/scripts/*.sh @devops-team
# Birden fazla sahip (hepsi reviewer olarak eklenir)
/src/payments/ @payment-team @security-team @tech-lead⚠️ Dikkat: CODEOWNERS dosyasının çalışması için branch protection rules'da "Require review from Code Owners" ayarının açık olması gerekir. Aksi halde dosya var olsa da zorunlu review uygulanmaz.
Approval Workflow — Onay Akışı
Branch Protection ile Zorunlu Review
Repository ayarlarında branch protection rules tanımlayarak review'ı zorunlu kılabilirsin:
Settings → Branches → Branch protection rules → Add rule
Branch name pattern: main
☑ Require a pull request before merging
☑ Require approvals
Required number of approvals: 2
☑ Dismiss stale pull request approvals when new commits are pushed
☑ Require review from Code Owners
☑ Restrict who can dismiss pull request reviews
☑ Require status checks to pass before merging
☑ Require branches to be up to date before merging
Search for status checks: ci/tests, ci/lint
☑ Require conversation resolution before merging
☐ Do not allow bypassing the above settings
(Bu açıksa admin bile bypass edemez)Onay Akışı Diyagramı
PR Açıldı
│
▼
CI Testleri ──── ❌ Fail ──► Merge bloklanır, developer düzeltir
│
✅ Pass
│
▼
CODEOWNERS Review ──── ❌ Changes Requested ──► Developer düzeltir
│ │
✅ Approved │
│ ◄─────────────┘
▼
Minimum 2 Approval ──── ❌ Yetersiz ──► Bekle
│
✅ 2+ Approval
│
▼
Conversations Resolved? ──── ❌ ──► Çözülmemiş tartışmalar var
│
✅ Tümü çözüldü
│
▼
Conflict var mı? ──── ❌ ──► Conflict'i çöz
│
✅ Temiz
│
▼
✅ MERGE EDİLEBİLİR! 🎉Stale Review Dismissal
Önemli bir güvenlik özelliği: bir reviewer onayladıktan sonra PR sahibi yeni commit push ederse, onay otomatik olarak geçersiz olabilir.
1. Reviewer onayladı ✅
2. PR sahibi yeni commit push etti
3. Önceki onay "stale" (bayat) olarak işaretlenir
4. Reviewer'ın tekrar incelemesi gerekir
Bu, "onay aldıktan sonra gizlice kod değiştirme" sorununu önler.Review Best Practices
Reviewer İçin
1. HIZLI OL
PR'lar 24 saat içinde incelenmeli. Uzun bekleme:
- Developer'ın context'ini kaybetmesine
- Merge conflict riskinin artmasına
- Ekip moralinin düşmesine yol açar
2. NAZIK OL
❌ "Bu kod çöp"
❌ "Neden böyle yazdın?"
✅ "Bu yaklaşım yerine şunu deneyebilirsin, çünkü..."
✅ "Güzel düşünmüşsün! Bir de şunu eklersek daha sağlam olur"
3. NEDEN AÇIKLA
❌ "Bunu değiştir"
✅ "Bunu değiştirmemiz lazım çünkü N+1 sorgu problemi var.
Her döngü iterasyonunda veritabanına ayrı sorgu gidiyor,
100 kayıt için 100 sorgu yapılıyor. Eager loading ile
tek sorguda çözebiliriz."
4. ÖNCELİKLENDİR
Her yorumun aynı ağırlıkta olmamalı.
🔴 Blocking: "Güvenlik açığı var, düzeltilmeli"
🟡 Suggestion: "Bence böylesi daha iyi olur ama zorunlu değil"
⚪ Nit: "Burada bir boşluk fazla var" (bu için review bloklama)
5. İYİYİ DE SÖY
Sadece hata bulmak için değil, iyi yapılmış şeyleri de belirt.
"Bu abstraction çok temiz olmuş! 👏"
"Test coverage'ı artırmışsın, harika! 🎉"PR Sahibi (Author) İçin
1. SELF-REVIEW YAP
PR'ı açmadan önce kendi kodunu "Files changed"da oku.
Debug log'ları, TODO'lar, gereksiz dosyalar...
2. KÜÇÜK TUT
200-400 satır ideal. 1000+ satır → "LGTM" deyip geçilir.
3. BAĞLAM VER
"Bu neden gerekli?" sorusunu cevaplayacak açıklama yaz.
4. SAVUNMAYA GEÇME
Review bir saldırı değil, öğrenme fırsatı.
❌ "Ben zaten biliyorum ama öyle yazdım"
✅ "Haklısın, düzeltiyorum" veya "Şu sebepten böyle yapmıştım: ..."
5. TEŞEKKÜR ET
Reviewer vakit ayırıp kodunu okudu. Basit bir "teşekkürler,
düzelttim!" bile ilişkiyi güçlendirir.Review Otomasyonu
Otomatik Reviewer Atama
.github/auto_assign.yml veya GitHub'ın built-in ayarları ile otomatik reviewer atayabilirsin:
Settings → Code and automation → Actions → General
Veya GitHub App: "Auto Assign" gibi uygulamalar kullanabilirsin.CODEOWNERS + Branch Protection = Otomatik Review Akışı
1. Developer PR açar
2. CODEOWNERS'a göre reviewer otomatik atanır
3. CI testleri otomatik çalışır
4. Reviewer inceler ve onaylar
5. Tüm koşullar sağlanınca merge butonu aktif olur
6. Auto-merge etkinse, otomatik merge edilirLinter ve Format Kontrolleri
Review'dan önce otomatik kontroller yapılmalı. Böylece reviewer "burada noktalı virgül eksik" gibi trivial yorumlar yazmak yerine mantık ve mimari üzerine odaklanır:
# .github/workflows/pr-checks.yml
name: PR Checks
on: pull_request
jobs:
lint:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- run: npm ci
- run: npm run lint # ESLint
- run: npm run format:check # Prettier
- run: npm test # Jestİnsan reviewer'ın zamanı değerlidir.
Makinenin yapabileceği kontrolleri makineye bırak:
🤖 Makine: Format, lint, test, type check, coverage
🧑 İnsan: Mantık, mimari, güvenlik, okunabilirlik, naming💡 İpucu: "Nit" seviyesindeki format sorunlarını (boşluk, noktalı virgül, satır uzunluğu) review'da tartışmak yerine, ESLint + Prettier gibi araçlarla otomatize et. CI'da format kontrolü yaparak bu tartışmaları tamamen ortadan kaldır.
Review Metrikleri
Ekibinin review sürecini ölçmek ve iyileştirmek için takip edilebilecek metrikler:
┌──────────────────────────────────────────────────────────┐
│ REVIEW METRİKLERİ │
├──────────────────────────────────────────────────────────┤
│ │
│ 📊 Review Süresi (Time to Review) │
│ İlk review'a kadar geçen süre │
│ Hedef: < 24 saat │
│ │
│ 📊 PR Boyutu (PR Size) │
│ Değiştirilen satır sayısı ortalaması │
│ Hedef: < 400 satır │
│ │
│ 📊 Review Döngüsü (Review Cycles) │
│ Onaya kadar kaç review turuna ihtiyaç duyuldu │
│ Hedef: 1-2 tur │
│ │
│ 📊 Merge Süresi (Time to Merge) │
│ PR açılmasından merge'e kadar geçen süre │
│ Hedef: < 48 saat │
│ │
│ 📊 Yorum Yoğunluğu (Comment Density) │
│ PR başına düşen yorum sayısı │
│ Çok az = incelenmemiş, çok fazla = PR çok büyük │
│ │
└──────────────────────────────────────────────────────────┘Yaygın Code Review Hataları
1. "LGTM" Sendromu
❌ Reviewer: "LGTM" (Looks Good To Me)
5 dakikada 500 satır "inceledi"
Bu, inceleme yapmamakla aynı şey.
✅ En azından şunları kontrol et:
- Genel mimari uygunluk
- Güvenlik açıkları
- Edge case'ler
- Test coverage2. Nit-pick Cehennemi
❌ 50 yorum, hepsi "burada boşluk fazla", "burada tab yerine space"
Bu tür yorumlar developer'ı demoralize eder ve
gerçek sorunlardan dikkati dağıtır.
✅ Format sorunları için lint/prettier kullan
İnsan olarak mantık, mimari, güvenlik üzerine odaklan3. Gatekeeping
❌ "Ben olsam böyle yazmazdım" — ve her seferinde değişiklik istemek
Her developer'ın stili farklıdır. Doğru birden fazla yolla yazılabilir.
✅ Objektif kriterlere odaklan:
- Performans sorunu var mı?
- Güvenlik açığı var mı?
- Proje standartlarına uyuyor mu?
- Okunabilir mi?4. Review'dan Kaçınmak
❌ "Ben junior'ım, senior'ın kodunu nasıl review edeyim?"
✅ Junior'lar da review yapmalı:
- Anlamadığın yer = dokümantasyon eksikliği
- "Bu ne yapıyor?" sorusu bile değerli geri bildirim
- Review yapmak, kodu anlamayı ve öğrenmeyi hızlandırırPratik: Eksiksiz Code Review Senaryosu
Şimdi bir PR'ı profesyonelce review edelim:
# PR #53: "feat: Add shopping cart functionality"
# +187 lines, -23 lines, 4 files changed
# src/cart.js — EKLENEN KOD:
+ const cart = [];
+
+ function addItem(item) {
+ cart.push(item);
+ }
+
+ function removeItem(id) {
+ for (let i = 0; i < cart.length; i++) {
+ if (cart[i].id == id) {
+ cart.splice(i, 1);
+ break;
+ }
+ }
+ }
+
+ function getTotal() {
+ let total = 0;
+ for (let i = 0; i < cart.length; i++) {
+ total += cart[i].price;
+ }
+ return total;
+ }
+
+ function applyDiscount(code) {
+ if (code == "SUMMER20") return getTotal() * 0.8;
+ if (code == "VIP50") return getTotal() * 0.5;
+ return getTotal();
+ }Profesyonel Review Yorumları:
### Genel Değerlendirme
İyi bir başlangıç! Cart mantığı temelde çalışıyor.
Birkaç önemli iyileştirme öneriyorum:
---
**Satır 1** — 🔴 [blocking]
Global mutable state anti-pattern. `const cart = []` modül seviyesinde
olmamalı. Class veya factory function kullan:
```suggestion
class ShoppingCart {
#items = [];
addItem(item) { ... }
removeItem(id) { ... }
}Satır 10 — 🟡 [suggestion] == yerine === kullan (strict equality). == type coercion yapar, "42" == 42 true döner ki bu beklenmeyen davranışlara yol açar.
Satır 9-14 — 🟡 [suggestion] for + splice yerine filter daha temiz:
removeItem(id) {
this.#items = this.#items.filter(item => item.id !== id);
}Satır 17-21 — 🟡 [suggestion] for loop yerine reduce kullanabilirsin:
getTotal() {
return this.#items.reduce((sum, item) => sum + item.price, 0);
}Satır 24-27 — 🔴 [blocking] Discount kodları hardcoded olmamalı. Veritabanından veya config'den gelmeli. Ayrıca 0.8 gibi magic number'lar yerine açıklayıcı yapı kullan:
const DISCOUNTS = {
'SUMMER20': 0.20,
'VIP50': 0.50,
};
applyDiscount(code) {
const discountRate = DISCOUNTS[code] || 0;
return this.getTotal() * (1 - discountRate);
}Genel — 💬 [question] Aynı ürünü birden fazla kez ekleyince ne olacak? Miktar (quantity) takibi yapmayı düşündün mü?
Genel — 💬 [todo] Test dosyası göremedim. Bir sonraki commit'te unit testler eklenmeli.
Satır 3 — ⭐ [praise] addItem fonksiyonunun basitliği güzel, KISS prensibi 👍
---
## Özet
Bu derste code review'ın tüm boyutlarını öğrendik:
- **Code review** sadece hata bulmak değil, bilgi paylaşımı, mentorluk ve kalite güvencesidir — production bug'larının %60'ından fazlası review ile yakalanabilir
- **Yorum türleri** — `[blocking]`, `[suggestion]`, `[nit]`, `[question]`, `[praise]` gibi öneklerle yorumun ciddiyetini netleştir
- **Suggesting changes** ile reviewer doğrudan kod önerisi yapar, PR sahibi tek tıkla uygular — en verimli geri bildirim yöntemi
- **CODEOWNERS** dosyası ile hangi kodun kimin sorumluluğunda olduğunu tanımla — ilgili dosyalar değişince otomatik reviewer atanır
- **Branch protection** ile review'ı zorunlu kıl — minimum onay sayısı, CI testleri, CODEOWNERS review'ı gibi koşullar belirle
- **Reviewer olarak** nazik ol, neden açıkla, önceliklendir ve iyiyi de söyle — review bir saldırı değil, ekip çalışması
Bir sonraki bölümde Git'in en güçlü ve en tartışmalı aracını göreceğiz: **Rebase**.
AI Asistan
Sorularını yanıtlamaya hazır