GitLab Merge Request ve Code Review Süreci
Bir ekiple kod yazıyorsanız ve hâlâ “benim makinemde çalışıyor” diyerek PR açıyorsanız, bu yazı tam size göre. GitLab’ın merge request sürecini doğru kullanmak, hem kod kalitesini artırıyor hem de ekip içi iletişimi çok daha sağlıklı bir zemine taşıyor. Yıllarca farklı ekiplerde çalıştım; iyi kurgulanmış bir code review süreci olmayan projelerde ne kadar zaman harcandığını, ne kadar teknik borç biriktiğini gördüm. Hadi bunu düzgünce kuralım.
GitLab Merge Request Nedir, Neden Önemlidir
Merge request (MR), bir branch’teki değişikliklerin ana branch’e alınmadan önce incelenmesi için açılan resmi bir taleptir. GitHub’daki pull request ile aynı mantıkta çalışır, ama GitLab’ın sunduğu ek özellikler iş akışını çok daha güçlü kılar: inline comment, approval rules, CI/CD entegrasyonu, draft MR, protected branch politikaları…
Kötü kurgulanmış bir ekipte şunu görürsünüz: Geliştirici kodu yazar, direkt main’e push’lar, sonra bir şeyler patlar ve herkes birbirine bakar. İyi kurgulanmış bir ekipte ise her değişiklik bir MR üzerinden geçer, en az bir kişi inceler, testler yeşile döner ve ancak ondan sonra merge edilir. Bu fark, prodüksiyon olaylarının sıklığını doğrudan etkiler.
Branch Stratejisi: MR’dan Önce Gelen Adım
Merge request açmadan önce doğru bir branch stratejisine ihtiyaç var. En yaygın yaklaşım GitFlow’un sadeleştirilmiş versiyonudur: main korunur, her feature veya fix için ayrı bir branch açılır.
# Yeni bir feature branch'i oluşturmak
git checkout main
git pull origin main
git checkout -b feature/user-authentication
# Ya da doğrudan GitLab issue'ya bağlı branch oluşturmak
# GitLab UI'da issue sayfasından "Create branch" tıklanabilir
# ya da CLI ile:
git checkout -b 42-kullanici-giris-modulu
Branch isimlendirmesi önemlidir. fix, test, deneme gibi isimler gördüğümde içim sıkışıyor. Açıklayıcı, kısa ve anlamlı isimler kullanın:
- feature/: Yeni özellik geliştirme
- fix/ veya bugfix/: Hata düzeltmesi
- hotfix/: Prodüksiyona acil müdahale
- refactor/: Kod yeniden düzenleme
- docs/: Dokümantasyon güncellemesi
- chore/: Bağımlılık güncellemesi, küçük bakım işleri
İlk Commit’ten MR Açmaya: Doğru Workflow
Geliştirme sürecinde commit mesajlarını da ciddiye alın. Bir MR açtığınızda, reviewer’ın anlayabilmesi için commit geçmişi okunabilir olmalı.
# Kötü commit mesajı örnekleri (bunları yapmayın)
git commit -m "düzeltme"
git commit -m "asdf"
git commit -m "bitti"
# İyi commit mesajı formatı (Conventional Commits)
git commit -m "feat: kullanıcı giriş formu eklendi"
git commit -m "fix: boş email ile giriş denemesinde crash düzeltildi"
git commit -m "refactor: auth service dependency injection'a taşındı"
git commit -m "docs: API endpoint dokümantasyonu güncellendi"
Branch’inizde çalışmayı tamamladıktan sonra, main branch’in gerisinde kalmadığından emin olun:
# Main'den son değişiklikleri alıp branch'inizi güncelleyin
git fetch origin
git rebase origin/main
# Conflict varsa çözün
git add .
git rebase --continue
# Temizlenmiş history ile push
git push origin feature/user-authentication --force-with-lease
--force yerine --force-with-lease kullanmayı alışkanlık edinin. Bu flag, uzak branch’te başkasının değişikliği olup olmadığını kontrol eder ve varsa push’u reddeder. Birinin üstüne yazma riskini azaltır.
GitLab’da Merge Request Oluşturmak
Push’tan sonra GitLab genellikle otomatik olarak MR oluşturma linki gösterir. Ama manuel de oluşturabilirsiniz.
MR açarken dikkat edilmesi gereken alanlar:
- Title: Ne yapıldığını tek cümleyle anlatan, açıklayıcı bir başlık
- Description: Neyin neden yapıldığı, nasıl test edildiği, varsa ekran görüntüleri
- Assignee: MR’ı kimin merge edeceği ya da takip ettiği
- Reviewers: İnceleme yapacak kişiler
- Labels: Issue tracking için etiketler
- Milestone: Sprint veya versiyon bağlantısı
- Draft: Henüz review’a hazır değilse Draft olarak açın
Draft MR özelliği çok kullanışlı. Geliştirme devam ederken CI’ın çalışmasını istiyorsunuz ama review’a hazır değilsiniz; Draft açarsınız, CI çalışır, herkes ilerlemeyi görür ama merge edilemez.
# GitLab CLI (glab) ile MR oluşturmak
glab mr create
--title "feat: kullanıcı authentication modülü"
--description "Closes #42 - JWT tabanlı kullanıcı girişi eklendi"
--reviewer "ahmet.yilmaz,mehmet.kaya"
--label "feature,backend"
--draft
MR Açıklaması: Reviewer’ın Zamanına Saygı
İyi bir MR açıklaması, reviewer’ın kodu anlamak için ek soru sormadan inceleyebileceği bilgileri içerir. Ekibimizde şu template’i kullanıyoruz:
## Değişiklik Özeti
Bu MR, kullanıcı girişini JWT token tabanlı bir yapıya taşıyor.
Session-based auth kaldırıldı, stateless bir yapıya geçildi.
## Neden Bu Değişiklik?
Yatay ölçeklendirme yapıldığında session paylaşımı sorun çıkarıyordu.
Redis session store eklemek yerine stateless JWT tercih edildi.
## Test Edildi mi?
- [ ] Unit test yazıldı (auth.service.spec.ts)
- [ ] Postman ile manuel test yapıldı
- [ ] Staging ortamında çalıştırıldı
## Dikkat Edilmesi Gerekenler
Token expiry süresi .env üzerinden configüre ediliyor.
Mevcut session'lar bu deploy ile geçersiz kalacak, kullanıcılar yeniden giriş yapacak.
## İlgili Issue
Closes #42
Bu template’i GitLab’ın Settings > Merge Requests bölümünden default olarak tanımlayabilirsiniz. Her MR açıldığında otomatik dolu gelir.
Code Review Süreci: Reviewer Perspektifi
Review yapmak, sadece kodu okumak değildir. Aynı zamanda öğretmek, öğrenmek ve ekip standartlarını korumaktır. Bir review’da şunlara bakılır:
Fonksiyonellik: Kod istenen işi yapıyor mu? Güvenlik: SQL injection, XSS, yetkilendirme açıkları var mı? Performans: N+1 query, gereksiz döngü, büyük veri yükleme var mı? Okunabilirlik: Kodu ilk kez gören biri anlayabilir mi? Test kapsamı: Edge case’ler düşünülmüş mü? Standartlar: Ekip naming convention ve kod stiline uyulmuş mu?
GitLab’da inline comment çok güçlü. Satır üzerinde yorum bırakabilir, suggestion ekleyebilirsiniz:
# GitLab suggestion syntax - reviewer bunu yazarsa,
# geliştirici tek tıkla kodu değiştirebilir:
const token = jwt.sign(payload, process.env.JWT_SECRET, { expiresIn: ‘1h’ });
Bu özelliği az kullanan ekipler var, ama verimliliği ciddi artırıyor. Reviewer değişiklik önerisini kod olarak yazıyor, geliştirici “Apply suggestion” diyerek direkt commit’liyor.
Approval Rules: Zorunlu İnceleme Mekanizması
GitLab’ın approval rules özelliği, belirli koşullar sağlanmadan merge edilemeyen bir yapı kurmanızı sağlar. Bu özelliği ayarlamak için:
Settings > Merge Requests > Approval rules kısmına gidin.
Tipik bir yapı:
- Any approver: Herhangi 2 kişinin onayı
- Code owners: İlgili dosyaların sahibi olanların onayı
- Security team: Güvenlik dosyaları değiştiyse security ekibinden onay
CODEOWNERS dosyası bu işin merkezinde:
# .gitlab/CODEOWNERS dosyası
# Genel kural: her değişiklik için backend ekibinden onay
* @backend-team
# Güvenlik ile ilgili dosyalar için security ekibi zorunlu
/src/auth/ @security-team @senior-backend
/config/security.yml @security-team
# Frontend bileşenler için frontend lead
/frontend/components/ @frontend-lead
# CI/CD konfigürasyonu için DevOps ekibi
/.gitlab-ci.yml @devops-team
/helm/ @devops-team
Bu dosyayı repository’ye ekledikten sonra, bir dosya değiştiğinde ilgili kişiler otomatik olarak reviewer olarak eklenir. Artık “ben bilmiyordum” mazereti ortadan kalkar.
Protected Branches ve Merge Kısıtlamaları
Main ve production branch’lerini korumalısınız. GitLab’da bu ayar Settings > Repository > Protected Branches altında yapılır.
Tipik bir ayar:
- Allowed to merge: Maintainers (ya da belirli bir rol)
- Allowed to push: No one (direkt push yasak, her şey MR üzerinden)
- Require approval from code owners: Aktif
- All discussions must be resolved: Aktif (tüm yorumlar çözülmeden merge edilemesin)
- Pipelines must succeed: Aktif (CI yeşile dönmeden merge edilemesin)
Bu ayarları yapıktan sonra kimse “hızlıca düzelteyim” diye direkt main’e push yapamaz. Tüm değişiklikler izlenebilir hale gelir.
CI/CD ile MR Entegrasyonu
Her MR açıldığında veya güncellendiğinde otomatik pipeline çalışmalı. Basit bir .gitlab-ci.yml örneği:
stages:
- validate
- test
- security
- build
lint:
stage: validate
image: node:20-alpine
script:
- npm ci
- npm run lint
only:
- merge_requests
unit-tests:
stage: test
image: node:20-alpine
script:
- npm ci
- npm run test:unit -- --coverage
coverage: '/Liness*:s*(d+.?d*)%/'
artifacts:
reports:
coverage_report:
coverage_format: cobertura
path: coverage/cobertura-coverage.xml
only:
- merge_requests
sast:
stage: security
include:
- template: Security/SAST.gitlab-ci.yml
only:
- merge_requests
build:
stage: build
image: docker:24
services:
- docker:24-dind
script:
- docker build -t $CI_REGISTRY_IMAGE:$CI_COMMIT_SHA .
only:
- merge_requests
Bu pipeline, her MR’da lint, test, güvenlik taraması ve build yapıyor. Herhangi biri başarısız olursa merge engellenebilir. Coverage raporları da MR sayfasında görünür hale gelir.
Geri Bildirim Kültürü: Nasıl Yorum Yazılır
Teknik olarak doğru bir review bile yanlış tonlandığında ekip içi gerginliğe yol açabilir. Yıllar içinde öğrendim: iyi review, insanı küçümsemez, kodu sorgular.
Kötü yorum örnekleri:
- “Bu kod çok berbat.”
- “Neden böyle yaptın ki?”
- “Bu açıkça yanlış.”
İyi yorum örnekleri:
- “Bu yaklaşımda N+1 query riski var, şöyle bir çözüm düşünebiliriz: …”
- “Buradaki mantığı tam anlayamadım, biraz açıklar mısın? Belki birlikte daha sade bir yol bulabiliriz.”
- “Bu işe yarıyor ama şu kütüphane bunu built-in destekliyor, test etmeye değer olabilir.”
Aynı şekilde yorum alırken de savunmacı olmamak gerekiyor. “Neden böyle yaptın?” diye soran birinin niyetini iyi okuyun. Çoğunlukla gerçekten merak ediyordur.
MR Boyutu: Küçük Tutun
En çok yapılan hata, 3000 satır değişiklikle MR açmak. Kimse o MR’ı düzgünce incelemez. Gözlerim kararıyor böyle şeyleri görünce.
İdeal MR boyutu 200-400 satır değişiklik civarında. Büyük özellikler için feature flag kullanın veya değişikliği birden fazla MR’a bölün:
# Büyük bir feature'ı parçalara bölmek için
# önce altyapı MR'ı:
git checkout -b feature/auth-infrastructure
# Sadece altyapı değişikliklerini buraya koy
# Bu merge edildikten sonra:
git checkout -b feature/auth-jwt-implementation
# JWT implementasyonunu buraya koy
# Son olarak:
git checkout -b feature/auth-ui-integration
# UI entegrasyonunu buraya koy
Her MR bağımsız olarak test edilebilir ve anlamlı bir bütün oluşturmalı. “Sadece bir adım” prensibi.
Çakışmaları Yönetmek
Uzun süre açık kalan MR’larda conflict kaçınılmaz. Conflict’i çözme sorumluluğu MR’ı açan kişiye aittir.
# Main güncellenmiş, branch'inizi rebasing ile güncelleyin
git fetch origin
git rebase origin/main
# Conflict çıkan dosyaları düzenleyin
# Sonra:
git add conflict-cozulen-dosya.js
git rebase --continue
# Push
git push origin feature/user-authentication --force-with-lease
# Ya da merge tercih ediyorsanız (daha az temiz history ama daha güvenli):
git merge origin/main
# Conflictleri çöz
git push origin feature/user-authentication
Rebase mi merge mi tartışması hâlâ devam ediyor. Kişisel tercihim: feature branch’lerde rebase, main’e entegrasyon sırasında merge commit. Bu şekilde hem temiz bir history kalıyor hem de merge noktası kaybolmuyor.
MR Sonrası: Merge Stratejisi
GitLab’da üç merge stratejisi var:
- Merge commit: Her MR için ayrı merge commit oluşturulur, history daha az linear ama her birleşme noktası görünür
- Squash and merge: Tüm commit’ler tek commit’e sıkıştırılır, main history temiz kalır
- Rebase and merge: Commit’ler tek tek main’e eklenir, linear history
Büyük ekiplerde squash and merge tercih ediyorum. Main’de her feature için tek, açıklayıcı bir commit kalıyor. “feat: kullanıcı authentication modülü (#42)” gibi. Geçmişi okumak çok daha kolay oluyor.
Merge sonrası branch’i silin. GitLab’da “Delete source branch” seçeneği MR ayarında var, otomatik sildirin. Repository’de onlarca ölü branch birikmesini engeller.
# Lokal temizlik
git fetch --prune
git branch -d feature/user-authentication
# Merge edilmiş tüm local branch'leri temizlemek
git branch --merged main | grep -v "^* main" | xargs git branch -d
Gerçek Dünya Senaryosu: Hotfix Süreci
Prodüksiyonda bir şey patladı, saat gece 02:00. Panik yapmadan şöyle gidiyoruz:
# Main'den hotfix branch'i aç
git checkout main
git pull origin main
git checkout -b hotfix/payment-null-pointer-fix
# Düzeltmeyi yap, test et
git add .
git commit -m "fix: ödeme servisi null user kontrolü eklendi"
# Push ve MR aç - bu sefer WIP değil, direkt review'a hazır
git push origin hotfix/payment-null-pointer-fix
# glab ile hızlıca MR oluştur
glab mr create
--title "hotfix: ödeme servisi null pointer düzeltmesi"
--description "Prodüksiyonda #127 issue - null user objesinde crash oluyor"
--label "hotfix,critical"
--reviewer "senior-developer"
--target-branch main
Hotfix MR’larında bile en az bir kişi bakmalı. “Acil” diyerek review’u atlarsanız, “acil fix’in fix’ini” yapıyorsunuz bir hafta sonra. Bunu defalarca yaşadım.
Sonuç
GitLab MR ve code review süreci, bir ekibin yazılım kalitesini koruyabilmesinin en kritik mekanizmasıdır. Doğru branch stratejisi, anlamlı commit mesajları, iyi yazılmış MR açıklaması, zorunlu approval kuralları ve CI/CD entegrasyonu bir araya geldiğinde hem kod kalitesi yükseliyor hem de ekip içi bilgi transferi kendiliğinden gerçekleşiyor.
Bu sürecin oturması zaman alıyor. İlk haftalarda “neden bu kadar bürokratik?” diyenler olacak. Ama bir ay sonra “prodüksiyona nasıl bu kadar sağlam çıkıyoruz?” diye sorduklarında cevap burada. Süreci küçük adımlarla başlatın, ekibi kademeli olarak alıştırın, kural koymadan önce neden koyduğunuzu anlatın. Teknik araçlar önemli, ama en sonunda insanlar kullanacak bunları.
