Docker & DevOps

    Git Branch Stratejileri: Git Flow ve Trunk Based

    Git Flow, Trunk Based ve GitHub Flow modellerinin farkları ve ekibinize uygun dallanma düzenini seçme rehberi.

    12 dk okuma Güncellendi: 25 Ağustos 2026

    Bir ekipte iki kişiden fazla insan aynı depoya kod yazmaya başladığı anda ortaya hep aynı soru çıkar: kim nereye push edecek, canlıya hangi dal gidecek, acil bir yama çıkarmak gerekirse yarım kalmış özellikleri de beraberinde sürüklemeden nasıl yayınlayacağız? Git branch stratejileri tam olarak bu sorulara verilmiş, denenmiş cevaplardır. Strateji seçmemek de bir seçimdir; ancak bunun bedelini genellikle bir cuma akşamı, canlıda bozulan bir sürümle ödersiniz.

    Bu rehberde en yaygın üç modeli — Git Flow, Trunk Based Development ve GitHub Flow — gerçek komutlarla, hangi ekip ölçeğinde hangisinin işe yaradığını açıklayarak anlatacağım. Ayrıca dal isimlendirme, koruma kuralları, uzun ömürlü dalların yarattığı sapma (drift) sorunu ve bu modellerin CI/CD boru hatlarıyla ilişkisi üzerinde duracağım. Amacım size "doğru cevabı" dayatmak değil; ekibinizin dağıtım sıklığına ve ürününüzün sürüm modeline bakarak kendi kararınızı verebilmenizi sağlamak.

    Dallanma Stratejisi Aslında Hangi Sorunu Çözer#

    Bir dallanma stratejisi, teknik olarak git branch komutunun nasıl kullanılacağını değil, kodun hangi noktada "yayınlanabilir" sayıldığını tanımlar. Depodaki her dal aslında bir söz verir: "buradaki kod şu olgunlukta". main dalı "canlıda çalışan kod", develop "bir sonraki sürüme aday kod", feature/x ise "henüz kimseyi bağlamayan deneme" anlamına gelir. Ekip bu sözleşme üzerinde anlaştığında, kimin ne zaman merge edeceği tartışması kendiliğinden biter.

    İkinci ve daha az konuşulan işlevi, entegrasyon acısının ne zaman ödeneceğini belirlemesidir. Kodu ne kadar uzun süre ayrı bir dalda tutarsanız, birleştirme anında karşılaşacağınız çakışma o kadar büyür. Üç hafta yaşamış bir dalın merge'ü genellikle yarım günlük bir çakışma çözme seansına dönüşür ve o sırada verilen kararların çoğu yorgun kararlardır. Trunk Based yaklaşımı bu acıyı günlük küçük dozlara böler; Git Flow ise sürüm disiplini karşılığında daha büyük ama daha seyrek dozları kabul eder. Aradaki fark tam olarak budur.

    Bir dalın ne kadar yaşadığını görmek için basit bir komut yeterlidir:

    # Uzak dalları son commit tarihine göre sırala (en eskisi en üstte)
    git for-each-ref --sort=committerdate refs/remotes/origin \
      --format='%(committerdate:short)  %(refname:short)'
    
    # Belirli bir dalın main'den kaç commit geride/ileride olduğu
    git rev-list --left-right --count origin/main...origin/feature/fatura-pdf
    # Çıktı örneği:  42   7
    # 42 = main'de olup dalda olmayan, 7 = dalda olup main'de olmayan commit sayısı
    

    O 42 sayısı büyüdükçe merge riskiniz de büyüyor demektir. Bu tek satırlık ölçüm, hangi stratejinin işlediğine dair en dürüst göstergedir.

    Git Flow: Uzun Ömürlü Dallar ve Sürüm Disiplini#

    Git Flow, sürüm numaralı ürünler için tasarlanmış klasik modeldir. İki kalıcı dal ve üç geçici dal tipi vardır. main yalnızca yayınlanmış sürümleri taşır ve her commit'i bir etiketle (tag) işaretlenir. develop bir sonraki sürüme giden birikmiş işi tutar. Yeni bir iş develop'tan feature/... dalı açarak başlar, biten iş develop'a döner. Sürüm zamanı geldiğinde develop'tan bir release/1.4.0 dalı çıkarılır; bu dalda yalnızca hata düzeltmeleri ve sürüm hazırlıkları yapılır, yeni özellik girmez. Sürüm hazır olduğunda release dalı hem main'e hem develop'a merge edilir ve main etiketlenir. Canlıda acil bir hata çıkarsa main'den hotfix/... dalı açılır, düzeltilir ve yine iki dala birden merge edilir.

    Elle uygularsanız akış şöyle görünür:

    # Yeni özellik dalı develop'tan açılır
    git switch develop
    git pull --ff-only
    git switch -c feature/fatura-pdf-cikti
    
    # ... çalışma, commit'ler ...
    git push -u origin feature/fatura-pdf-cikti
    
    # Sürüm hazırlığı: develop'tan release dalı
    git switch -c release/1.4.0 develop
    # sürüm numarasını dosyalara işle, changelog yaz, sadece bugfix commit'le
    
    # Yayın: main'e merge + etiket
    git switch main
    git merge --no-ff release/1.4.0
    git tag -a v1.4.0 -m "1.4.0 sürümü: fatura PDF çıktısı ve ödeme hatırlatma"
    git push origin main --follow-tags
    
    # Aynı düzeltmeler develop'a da dönmeli, yoksa bir sonraki sürümde kaybolur
    git switch develop
    git merge --no-ff release/1.4.0
    git push origin develop
    

    Buradaki --no-ff bayrağı bilinçli bir tercihtir: ileri sarma (fast-forward) yerine gerçek bir birleştirme commit'i üretir, böylece geçmişte "bu grup commit bir sürümdü" bilgisi korunur. Git Flow'un en büyük gücü, birden fazla sürümü aynı anda desteklemesi gerekiyorsa (örneğin müşterilerin 1.3 ve 1.4 sürümlerini birlikte kullandığı kurumsal bir ürün) ortaya çıkar. En büyük zayıflığı ise develop ile main arasındaki sapmadır: iki dal haftalarca ayrı yaşadığında, main'e alınan bir hotfix develop'a geri taşınmayı unutulduğunda hata bir sonraki sürümde geri gelir. Bu, Git Flow kullanan ekiplerin bir numaralı üretim kazasıdır.

    Trunk Based Development: Tek Ana Dal, Kısa Ömürlü Sapmalar#

    Trunk Based Development'ın kuralı tek cümleyle özetlenir: herkes günde en az bir kez main dalına entegre olur. Dal açmak yasak değildir, ama dalın ömrü saatler veya en fazla bir gündür. Yarım kalmış işler depoya girmeye devam eder; görünmemesi gereken şeyler dal ile değil, özellik bayrağı (feature flag) ile kapatılır. Böylece main her an dağıtılabilir durumda kalır ve entegrasyon çakışmaları büyümeye fırsat bulamaz.

    Yarım bir özelliği bayrakla saklamak pratikte şuna benzer:

    ; config/features.ini — canlıda kapalı, geliştirmede açık
    [features]
    yeni_fatura_ekrani = 0
    toplu_odeme_bildirimi = 0
    

    Uygulama kodu bayrağa bakar; bayrak kapalıyken kullanıcı yeni ekranı hiç görmez ama kod main dalındadır, derlenir, test edilir ve diğer değişikliklerle çakışmaz. Özellik tamamlandığında yapılan tek şey bayrağı açmaktır — bu da bir kod dağıtımı değil, bir yapılandırma değişikliğidir ve geri alması saniyeler sürer.

    Trunk Based, sürekli dağıtım yapan ekipler için en verimli modeldir; ancak iki ön koşulu vardır ve bunlar pazarlıksızdır. Birincisi güçlü otomatik testler: main'e giren her commit derleme ve testten geçmelidir, çünkü koruyucu başka bir katman yoktur. İkincisi hızlı geri alma yeteneği: bozuk bir sürümü dakikalar içinde geri alabilmelisiniz. Bu iki koşul yoksa Trunk Based, disiplin değil kaos üretir. Commit'lerinizi anlamlı ve otomatik ayrıştırılabilir tutmak da işi kolaylaştırır; conventional commits ve semantic versioning yazısında bunun nasıl kurulduğunu adım adım anlattım.

    GitHub Flow ve GitLab Flow: Pratikteki Orta Yol#

    Çoğu web ekibinin gerçekte kullandığı model ne saf Git Flow ne de saf Trunk Based'dir. GitHub Flow, ikisinin arasında duran son derece yalın bir düzendir: tek kalıcı dal (main), her iş için kısa ömürlü bir dal, dal üzerinden açılan bir pull request, otomatik testler ve kod incelemesi, ardından main'e merge ve merge'ün hemen ardından dağıtım. Sürüm dalı yoktur, develop yoktur; "yayınlanmış sürüm" kavramı etiketlerle tutulur.

    GitLab Flow ise buna ortam dallarını ekler. main'e merge edilen kod otomatik olarak test ortamına gider; staging ve production dalları, main'den ileriye doğru yalnızca merge ile beslenir. Böylece hangi commit'in hangi ortamda çalıştığı dalın kendisinden okunabilir:

    # main -> staging: test ortamına terfi
    git switch staging
    git merge --ff-only main
    git push origin staging
    
    # staging -> production: canlıya terfi (yalnızca doğrulanmış commit'ler ilerler)
    git switch production
    git merge --ff-only staging
    git push origin production
    

    Buradaki --ff-only kritik: ortam dallarında bağımsız commit üretmeye izin vermez, yani canlıya yalnızca main'den geçmiş ve test edilmiş kod ilerleyebilir. Bu tek bayrak, "canlıda bizde olmayan bir düzeltme var" durumunu yapısal olarak imkânsız kılar. Hosting tarafında kodunuzu depodan doğrudan çekiyorsanız, hangi dalı çektiğiniz bu şemayla birebir eşleşmelidir; paylaşımlı hosting üzerinde bunu nasıl kuracağınızı cPanel Git Version Control yazısında bulabilirsiniz.

    Modelleri Yan Yana Koymak#

    Aşağıdaki tablo, üç modeli seçim anında bakacağınız ölçütlerle karşılaştırıyor. Kararınızı "hangisi daha modern" sorusuyla değil, "bizim dağıtım sıklığımız ne" sorusuyla verin.

    ÖlçütGit FlowGitHub FlowTrunk Based
    Kalıcı dal sayısı2 (main, develop)1 (main)1 (main)
    Dal ömrüGünler – haftalar1–5 günSaatler
    Sürüm modeliNumaralı, planlı sürümSürekli dağıtımSürekli dağıtım
    Aynı anda çoklu sürüm desteğiGüçlüZayıfZayıf
    Otomatik test zorunluluğuOrtaYüksekÇok yüksek
    Yarım işi saklama yöntemiDalDalÖzellik bayrağı
    Tipik ekip ölçeği6+ kişi, sürüm takvimi olan2–15 kişi, web ürünüOlgun CI/CD'si olan her ölçek
    Ana riskdevelop sapması, unutulan geri mergeUzayan pull request'lerZayıf testle bozuk main

    Pratik önerim şudur: masaüstü uygulaması, mobil uygulama, kurumsal lisanslı yazılım gibi sürüm numarasıyla dağıtılan ürünlerde Git Flow hâlâ mantıklıdır. Sürekli yayında olan web uygulamaları ve API'lerde GitHub Flow varsayılan seçiminiz olsun. Günde birden fazla dağıtım yapıyor ve test kapsamınıza güveniyorsanız Trunk Based'e geçin. Bunları karıştırmak yasak değildir; nitekim çoğu ekip GitHub Flow'a bir release/* dalı ekleyerek kendi melez modelini kurar. Yeter ki yazılı olsun ve herkes aynı şeyi anlasın.

    Dal İsimlendirme, Koruma Kuralları ve Otomasyon#

    İsimlendirme küçük bir detay gibi görünür ama depoda yüz dal olduğunda hayat kurtarır. Ekipte üzerinde anlaşılmış bir ön ek şeması, hem insanın hem otomasyonun dalı tanımasını sağlar:

    Ön ekKullanımÖrnek
    feature/Yeni işlevfeature/fatura-pdf-cikti
    fix/Hata düzeltmefix/sepet-kdv-yuvarlama
    hotfix/Canlıdaki acil düzeltmehotfix/odeme-callback-500
    chore/Bağımlılık, yapılandırma, temizlikchore/php-8-3-gecisi
    release/Sürüm hazırlığırelease/1.4.0

    Dal adına bilet numarasını eklemek (feature/1273-fatura-pdf) izlenebilirliği ciddi biçimde artırır. Türkçe karakter ve boşluk kullanmayın: Git izin verir ama kabuk (shell) betikleri, CI yapılandırmaları ve bazı dosya sistemleri sorun çıkarır.

    Ana dalı korumak isteğe bağlı değildir. GitHub, GitLab ve Bitbucket'ta main için şu üç kuralı açın:

    1. Doğrudan push kapalı — değişiklik yalnızca pull request ile girer.
    2. Zorunlu durum kontrolleri — testler ve derleme yeşil olmadan merge düğmesi açılmaz.
    3. Zorunlu inceleme — en az bir onay; kritik dizinler için kod sahipliği (CODEOWNERS) tanımlayın.

    Buna ek olarak git push --force komutunu paylaşılan dallarda tamamen yasaklayın; gerekiyorsa --force-with-lease kullanın, çünkü bu bayrak sizin bilmediğiniz bir commit uzakta varsa itmeyi reddeder. Yerel tarafta bu kuralların bir kısmını istemci düzeyinde de zorlayabilirsiniz; Git hooks ile otomasyon yazısında pre-push kancasıyla yanlış dala push'u nasıl engelleyeceğinizi gösterdim.

    Sık Yapılan Hatalar ve Tuzaklar#

    Uzun yaşayan özellik dalları. En pahalı hata budur. Üç haftadır açık duran bir dal, artık bir dal değil, ayrı bir üründür. Çözüm dalı daha hızlı bitirmek değil, işi bölmektir: özelliği arkada kalan (ve bayrakla kapalı) küçük parçalar hâlinde main'e taşıyın. Dal ömrünüzü haftalık ölçün; ortalama üç günü aşıyorsa modeliniz değil, iş kırılımınız bozuktur.

    Hotfix'i geri taşımamak. Git Flow kullanan ekiplerde klasik senaryo: main'de acil düzeltme yapılır, canlı kurtarılır, herkes rahatlar ve düzeltme develop'a merge edilmez. Bir sonraki sürümde aynı hata geri gelir ve bu kez nedenini kimse anlayamaz. Hotfix akışını iki merge'lü tek bir kontrol listesi hâline getirin; mümkünse bunu CI'da zorlayın.

    Ortam dallarında bağımsız commit. production dalına doğrudan yapılan "küçük bir düzeltme", o dalı main'den kalıcı olarak ayırır ve bir daha asla ileri sarma ile merge edemezsiniz. Ortam dallarını salt ilerleyen (--ff-only) tutun.

    Rebase ile merge'ü karıştırmak. Paylaşılan bir dalı rebase etmek, diğer herkesin geçmişini bozar. Kişisel dalınızı main'e göre güncel tutmak için rebase, paylaşılan dalı entegre etmek için merge kullanın. İkisinin tam olarak neyi değiştirdiğini Git rebase ve merge farkı yazısında ayrıntılı ele aldım.

    Etiket atmayı unutmak. Sürüm dalı olmayan modellerde tek geri dönüş noktanız etiketlerdir. main'e giden her dağıtımı etiketleyin ve etiketleri --follow-tags ile itmeyi alışkanlık hâline getirin. Etiketsiz bir depoda "geçen salı canlıda ne vardı" sorusunun cevabı yoktur.

    Depoya girmemesi gerekenler. Dallanma modeliniz ne olursa olsun, ortam dosyalarını ve anahtarları depoya koymayın. Bir kez commit edildiğinde geçmişten silmek zahmetli, sızdıktan sonra ise imkânsızdır; konuyla ilgili risk ve temizlik adımlarını .git ve .env dosyası ifşası yazısında bulabilirsiniz.

    Sıkça Sorulan Sorular#

    Küçük bir ekip için hangi git branch stratejisi en uygun#

    İki ile beş kişilik ekiplerde GitHub Flow neredeyse her zaman doğru cevaptır: tek main dalı, iş başına kısa ömürlü bir dal, pull request üzerinden inceleme ve merge sonrası dağıtım. Git Flow'un develop ve release katmanları bu ölçekte fayda değil bürokrasi üretir. Ekip büyüdüğünde ya da sürüm takvimi ortaya çıktığında modeli genişletmek, baştan karmaşık kurup sadeleştirmekten çok daha kolaydır.

    Git Flow artık kullanılmıyor mu#

    Kullanılıyor, ama eskisi kadar geniş bir alanda değil. Sürekli dağıtım yapan web ürünlerinde Git Flow'un uzun ömürlü dalları gereksiz gecikme yaratır. Buna karşılık aynı anda birden fazla sürümü desteklemek zorunda olan masaüstü, gömülü ve kurumsal lisanslı yazılımlarda hâlâ en pratik modeldir. Sorunuzu "modern mi" değil, "aynı anda kaç sürümü canlı tutuyoruz" diye sorarsanız cevabı kendiliğinden bulursunuz.

    Trunk Based Development için özellik bayrağı şart mı#

    Pratikte evet. Trunk Based, yarım kalmış işin de main dalında durmasını kabul eder; o işi kullanıcıdan saklamanın tek yolu bayraktır. Bayrak olmadan ya yarım özellikler canlıya sızar ya da geliştiriciler gizli gizli uzun ömürlü dallar açmaya başlar ki bu da modeli baştan geçersiz kılar. Bayrak altyapısı basit bir yapılandırma anahtarı kadar sade olabilir, karmaşık bir ürün gerektirmez.

    Özellik dalı ne kadar süre açık kalmalı#

    Hedef bir gün, üst sınır ise beş iş günüdür. Bu süreyi aşan her dal, birleştirme çakışması ve inceleme yorgunluğu riskini katlanarak artırır. Bir iş beş günden uzun sürüyorsa dalı uzatmak yerine işi bölün: önce veritabanı değişikliği, sonra arka uç, sonra arayüz gibi bağımsız merge edilebilir parçalara ayırın. Dal ömrü, bir ekibin süreç sağlığını gösteren en iyi tek metriktir.

    main ve master dalını nasıl değiştiririm#

    Yeni depolarda varsayılanı git config --global init.defaultBranch main ile ayarlarsınız. Mevcut bir depoda ise git branch -m master main ile yerelde adı değiştirir, git push -u origin main ile itersiniz; ardından uzak sunucudaki varsayılan dalı arayüzden main yapar ve eski dalı git push origin --delete master ile silersiniz. Değişiklikten sonra CI yapılandırmalarında ve dağıtım betiklerinde geçen dal adlarını taramayı unutmayın.

    Dal koruma kurallarını açmak geliştirmeyi yavaşlatır mı#

    Kısa vadede birkaç dakika ekler, uzun vadede saatler kazandırır. Zorunlu testler ve tek onay kuralı, canlıya bozuk kod gitmesini engelleyerek en pahalı gecikmeyi ortadan kaldırır. Yavaşlama hissi genellikle kurallardan değil, incelemede bekleyen dev pull request'lerden kaynaklanır; değişiklikleri küçük tuttuğunuzda inceleme süresi de dakikalar seviyesine iner.

    Kapanış#

    Dallanma stratejisi seçimi teknik bir tercih gibi görünse de aslında bir ekip anlaşmasıdır. Aklınızda kalması gereken dört şey var: dalın ömrünü kısa tutun, main dalını her zaman dağıtılabilir durumda bırakın, ortam dallarını yalnızca ileri saracak biçimde besleyin ve her yayını etiketleyin. Modeli yazılı hâle getirip depo kökündeki bir CONTRIBUTING.md dosyasında paylaşın; kafalardaki model, yazılı olmayan modeldir ve iki hafta sonra herkes farklı hatırlar.

    Seçtiğiniz akışı çalıştıracak altyapıyı da düşünmek gerekir: test ve hazırlık ortamlarını ayrı tutmak, dağıtımı otomatikleştirmek ve geri alma senaryosunu önceden denemek. Kendi CI koşucunuzu ve hazırlık ortamınızı barındırmak için tam root erişimli VDS veya sanal sunucu paketlerimizi kullanabilir, sunucu bakımını üstlenmemizi isterseniz sunucu yönetimi hizmetimize bakabilirsiniz. Depodan canlıya geçişi paylaşımlı bir ortamda kuruyorsanız web hosting paketlerimizdeki Git desteği çoğu küçük proje için fazlasıyla yeterlidir.

    GitDevOpsSürüm Yönetimi

    Uygulamaya geçmeye hazır mısınız?

    NVMe SSD, ücretsiz SSL ve %99.9 uptime garantisiyle Clou.TR hosting ve sunucu çözümleriyle projenizi hayata geçirin.