Bölüm 7 / 12
Branching stratejileri
GitFlow, trunk-based, feature branch.
18 dakikalık okuma
İlk altı ders tek kişinin Git'iydi: komutlar, graf, geri alma. Bu ders ekibin Git'ine geçer. Git dallanmayı bedavaya verir; hangi dalların açılacağı, ne kadar yaşayacağı ve main'e nasıl gireceği ise Git'in değil ekibin kararıdır — ve 1. dersin tanımıyla bir sosyal sözleşmedir. Ders üç yerleşik stratejiyi (GitFlow, GitHub Flow, trunk-based) mekanizmasıyla ve maliyetiyle anlatır; sürüm ve hotfix akışını, "PR düğmesinin üç seçeneği"ni (3. ve 6. dersin senedi) ve 3. dersten beri ertelenen trunk-based ↔ GitFlow tartışmasını kapatır. Bitişte bir karar tablosu vardır: sözlüde "ekibinizde hangi stratejiyi kullanırsınız" sorusuna tek kelimeyle değil, gerekçeli bir seçimle cevap vereceksin.
01Ne öğreneceksin
- Stratejinin üç sorusu: dallar nasıl düzenlenir, ne kadar yaşar, main'e nasıl girer; strateji ↔ entegrasyon sıklığı bağı
- GitFlow: beş dal türü, akış, uygun olduğu yer ve gizli maliyeti (çift merge, uzun ömürlü develop)
- GitHub Flow ve GitLab Flow: "main her an dağıtılabilir"; ortam ve sürüm dalları
- Trunk-based development: kısa dallar, özellik bayrağı, soyutlamayla dallanma, ön şartları
- Sürüm ve hotfix akışı: release dalı yalnız kesim için, düzeltme main'de,
cherry-pick -x, annotated tag - Merge davranışı kararı: merge commit / squash / rebase-ff — PR düğmesinin üç seçeneği ve sonuçları
- Dal koruma kuralları, isimlendirme, monorepo notu; DORA metrikleri ile dal ömrünün bağı
- "Hangi durumda hangisi" karar tablosu ve kamu kurumu senaryosu
02Strateji nedir ve neden ekip kararıdır
3. ders dalı 41 baytlık bir dosya olarak tanıttı; açmak ve silmek bedava. Ama bir dal yaşadığı sürece ekip için bir soru üretir: bu daldaki iş ne zaman herkesin işiyle buluşacak? 5. ders bunun bedelini gösterdi — dal ne kadar uzun yaşarsa merge o kadar pahalı, çatışma o kadar büyük. Bir branching stratejisi, ekibin şu üç soruya verdiği yazılı cevaptır:
- Dallar nasıl düzenlenir? Hangi kalıcı dallar var (yalnız main mi, develop de var mı, ortam dalları var mı), geçici dallar hangi türde açılır, adları nedir.
- Dallar ne kadar yaşar? Saatler mi, günler mi, sürüm boyunca mı — bu, entegrasyon sıklığının doğrudan ölçüsüdür.
- İş main'e nasıl girer? Doğrudan commit mi, PR mi; merge commit mi, squash mı, rebase mi; kimin onayıyla; hangi kontrollerden sonra.
Bu cevapların hiçbirini Git dayatmaz — 1. dersin "sunucu = sosyal sözleşme" cümlesinin devamıdır: Git her modeli aynı kolaylıkla taşır. Ekip ise yalnızca birini seçmek zorundadır, çünkü strateji üstüne kurulan her şey (CI'ın hangi dalda koşacağı, sürümün nereden kesileceği, hotfix'in nereye gideceği) o seçime bağlıdır. Stratejilerin hepsi tek bir eksende sıralanır: entegrasyon ne kadar sık? Bir uçta haftalar süren dallar ve büyük birleştirmeler, diğer uçta günde birkaç kez main'e giren küçük commit'ler. Bu dersin üç stratejisi o eksenin üç noktasıdır; kalan her şey ayrıntıdır.
03GitFlow
2010'da Vincent Driessen'in yayımladığı model, uzun süre "Git böyle kullanılır" sanılan ilk yerleşik stratejidir. İki kalıcı, üç geçici dal türü vardır:
| Dal | Ömür | Nereden açılır | Nereye birleşir | Anlamı |
|---|---|---|---|---|
main | kalıcı | — | — | Yalnız üretimdeki sürümler; her commit'i bir sürüm tag'i |
develop | kalıcı | main'den bir kez | release üzerinden main'e | Bir sonraki sürümün entegrasyon dalı |
feature/* | günler–haftalar | develop | develop | Tek özellik |
release/* | günler | develop | main ve develop | Sürüm dondurma: yalnız hata düzeltme, sürüm numarası, doküman |
hotfix/* | saatler | main | main ve develop | Üretimdeki acil düzeltme |
main ── v1.0 ──────────────────────── v1.0.1 ─────────── v1.1 ──
│ ▲ ▲
│ hotfix/1.0.1 ───┤──┐ │
│ │ │ release/1.1 ──┤──┐
develop ─────┴── o ── o ── o ── o ── o ── o ┴──┴── o ── o ────────┴──┴── o ──
│ ▲
└ feature/x ───┘
Akış: özellik develop'tan açılır, develop'a döner; sürüm zamanı develop'tan
release/1.1 kesilir, orada yalnız düzeltme yapılır, bitince
hem main'e hem develop'a merge edilir ve main'de v1.1
tag'lenir (4. ders: annotated). Üretimde hata çıkarsa main'den hotfix/1.0.1
açılır, o da iki yere birden merge edilir. Uygun olduğu yer bellidir: paketlenip
müşteriye teslim edilen yazılım, aynı anda birden fazla sürümün üretimde desteklenmesi
(1.0 kullanan müşteri hâlâ yama alıyor), sürüm arasında resmî bir dondurma ve onay evresi
gerektiren düzenleyici ortamlar.
Maliyeti tablodaki iki koyu hücrede saklıdır. Release ve hotfix dalları iki yere
merge edilir; birini unutmak klasik GitFlow hatasıdır — üretimde düzeltilen hata bir
sonraki sürümde geri gelir, çünkü develop'a hiç girmemiştir. İkincisi,
develop uzun ömürlü bir entegrasyon dalıdır: özellikler haftalarca kendi
dallarında yaşar, develop'ta buluşur, main'e ancak sürümde ulaşır; 5. dersin "büyük
çatışma" ve 3. dersin "merge geciktikçe pahalanır" uyarısı tam bu modelin günlük hayatıdır.
Üçüncüsü, "sürekli dağıtım" ile uyumsuzdur: main yalnız sürümlerde ilerler, günde beş
dağıtım yapan bir web uygulaması için dal töreni iş yükünden fazladır. Driessen bunu
2020'de yazısına eklediği notla kendisi söyledi: sürekli teslimat yapan ekipler daha
basit bir akışa, GitHub Flow'a bakmalı. Sözlüde GitFlow'u anlatırken bu iki cümleyi
birlikte söyleyebilmek — "ne zaman uygun" ve "ne zaman fazla" — kıdemi gösterir.
04GitHub Flow ve GitLab Flow
GitHub Flow tek kalıcı dal tanır: main, ve bir kural koyar —
main her an dağıtılabilir olmalıdır. Her iş kısa ömürlü bir daldan açılır,
PR ile (8. ders) tartışılır ve doğrulanır, birleştiğinde dağıtılır. Özgün tarifte
dağıtım merge'den önce gelir: dal üretime alınır, sorun çıkmazsa main'e
girer; çoğu ekip bugün "merge = dağıt" olarak uygular. Sürüm dalı, develop, hotfix töreni
yoktur: hotfix de sıradan bir kısa daldır, çünkü main zaten üretimdir.
main ── o ── o ── o ──────── M ── o ─── M ── o ──
└ ozellik/… ┘ └ hotfix/… ┘ (her M = PR merge → dağıtım)
Uyduğu yer: tek üretim ortamı olan, sık dağıtılan web uygulaması ve servisler. Uymadığı
yer: aynı anda birden fazla sürümü desteklemek, dağıtım tarihinin kurumca belirlendiği
"pencere" düzeni, ya da "main'e girdi ama henüz yayınlanmadı" ara durumunu temsil etme
ihtiyacı. GitLab Flow bu boşluklar için iki uzantı önerir: ortam dalları
(main → staging → production; kod aşağı doğru yalnız merge ile akar, dağıtım
= ilgili dala merge) ve sürüm dalları (release/1.4, yalnız
düzeltme alır). Her iki uzantıda da tek kural vardır ve bu dersin en önemli ilkelerinden
biridir: "upstream first" — düzeltme önce main'de yapılır, sonra ortam/sürüm dalına
taşınır; asla tersi. Aksi hâlde GitFlow'un "unutulan ikinci merge" hatası başka adla geri
gelir.
05Trunk-based development
Eksenin sık entegrasyon ucu. Tek kalıcı dal (trunk = main), herkes ona en az günde bir commit gönderir: ya doğrudan (küçük, disiplinli ekiplerde), ya ömrü bir-iki günü geçmeyen kısa dallardan PR ile. 3. dersin cümlesi buradan geliyordu: "dal ne kadar uzun yaşarsa merge o kadar pahalı" — trunk-based bu bedeli sıfıra yakın tutmak için dalı kısa tutar. Haftalar sürecek bir iş nasıl günlük parçalarla main'e girer? İki teknikle:
Özellik bayrağı (feature flag). Yeni kod yolu main'e girer ama bir anahtarla kapalı durur; bayrak açılana kadar kullanıcı görmez. Yayın, dağıtımdan ayrılır: kod haftalar önce üretimdedir, "açma" bir yapılandırma değişikliğidir — istenirse yalnız belli kullanıcılara (yüzde, kurum, rol) açılır, sorun çıkarsa kod geri alınmadan kapatılır.
if (bayraklar.Acik("yeni-ucret-hesabi", basvuru.KurumId))
return yeniHesap.Hesapla(basvuru);
return eskiHesap.Hesapla(basvuru);
Bayrakların türü farklıdır ve ömürleri de: release bayrağı (bitmemiş özelliği
saklar; günler-haftalar, bitince silinir), deney bayrağı (A/B; deney
bitince silinir), işletim bayrağı (yük altında pahalı özelliği kapatmak; kalıcı
olabilir, 19. hattın devre kesicisine komşu), yetki bayrağı (belirli kullanıcılara
erken erişim). Kıdem kuralı: her bayrak teknik borçtur (15-11) — açılış tarihi ve
son kullanma tarihi olmayan bayrak, iki yıl sonra kimsenin dokunmaya cesaret edemediği
ölü bir if olur; bayrak kaldırma işi backlog'a bayrakla aynı gün yazılır.
Test tarafı da vardır: bayrağın iki hâli de test edilir, kombinasyon patlamasına karşı
bayrak sayısı az tutulur.
Soyutlamayla dallanma (branch by abstraction). Büyük bir değişimi (ORM değiştirmek, ödeme sağlayıcısını taşımak) dalda değil main'de, adım adım yapmak: eski uygulamanın önüne bir arayüz konur, çağıranlar arayüze taşınır, yeni uygulama arayüzün arkasında bayrakla büyütülür, tamamlanınca eski kaldırılır. Her adım küçük, her adım main'de, hiçbir adımda çalışan sistem bozulmaz — 4. hattın DIP'i (tas-solid-dip) ve 15-11'in strangler deseni burada süreç aracı olur.
Trunk-based'in sürüm dalı vardır ama farklı anlamda: yalnız kesim için
(branch for release). Sürüm zamanı main'den release/1.4 açılır, tag'lenir,
dağıtılır; üzerinde geliştirme yapılmaz, düzeltme main'de yapılıp cherry-pick -x
ile taşınır (06. bölüm). Ön şartları vardır ve pazarlıksızdır: hızlı CI (her push'ta
dakikalar içinde build + test — 18. hat), güvenilir test ağı (15. hat; main her an
dağıtılabilir olacaksa "sonra test ederiz" yoktur), küçük ve atomik commit'ler (2. ders),
kod incelemesinin dalı bekletmemesi (8. ders: saatler, günler değil). DORA'nın yıllık
"State of DevOps" araştırmaları yıllardır aynı bulguyu veriyor: az sayıda aktif dal ve
bir günden kısa dal ömrü, yüksek performanslı ekiplerle güçlü biçimde ilişkili. Bu
nedensellik değil korelasyon; ama mekanizması açık — küçük parça, küçük risk, hızlı geri
bildirim.
06Sürüm ve hotfix akışı
Sözlüde "sürüm nasıl çıkar" sorusu, stratejiden bağımsız olarak şu adımların bilinmesini bekler; adımların dağılımı stratejiye göre değişir ama parçalar aynıdır:
- Kesim. Sürüme girecek son commit belirlenir. GitFlow'da develop'tan release
dalı; trunk-based'de main'den
release/1.4(ya da yalnız tag). Sürüm numarası SemVer (15-11): kırıcı değişiklik MAJOR, geriye uyumlu özellik MINOR, düzeltme PATCH. - Dondurma. Release dalına yalnız düzeltme girer; yeni özellik main'e (ya da develop'a) akmaya devam eder. "Bu da girsin" isteğinin cevabı hayırdır; sürüm dondurulmazsa hiç çıkmaz.
- Tag. Dağıtılan commit
git tag -a v1.4.0 -m "…"ile işaretlenir ve--follow-tagsile push edilir (4. ders). Tag taşınmaz; hata varsav1.4.1gelir.git describederleme numarasını bu tag'den türetir (18. hat). - Dağıtım + duyuru. Changelog (11. ders) ve dağıtım (18. hat).
Hotfix akışında iki okul vardır ve farkı bilmek sınav sorusudur. GitFlow okulu: düzeltme main'den (üretimden) açılan hotfix dalında yapılır, main'e ve develop'a merge edilir. Trunk-based / GitLab okulu (upstream first): düzeltme main'de yapılır, test edilir, sonra sürüm dalına taşınır:
git switch main && git switch -c fix/son-gun-saati
…düzelt, test et, PR ile main'e al… (main'de commit: 3f2a1c0)
git switch release/1.4
git cherry-pick -x 3f2a1c0 (6. ders: -x kaynağı mesaja yazar)
git tag -a v1.4.1 -m "Son gün 23:59 hatası" && git push --follow-tags origin release/1.4
git cherry main release/1.4 (taşınmamış commit kaldı mı?)
İkinci okulun gerekçesi: düzeltmenin gelecek sürümde unutulması imkânsızdır,
çünkü zaten main'dedir; sürüm dalı her zaman main'in bir alt kümesidir; ve
git cherry ile "hangi düzeltme hangi sürüme taşındı" denetlenebilir. Birden
fazla sürümün destekte olduğu üründe (1.3 ve 1.4 aynı anda) aynı commit her destekli
sürüm dalına ayrı ayrı cherry-pick edilir — destek penceresi ne kadar genişse bakım
maliyeti o kadar büyür; "kaç sürümü destekliyoruz" bir ürün kararıdır ve dal sayısını
belirler.
07Merge davranışı kararı: PR düğmesinin üç seçeneği
3. ve 6. dersin senedi. Bitmiş iş main'e üç biçimde girer ve barındırma platformları
PR düğmesinde tam bu üçünü sunar (GitHub: "Create a merge commit / Squash and merge /
Rebase and merge"; Azure DevOps ve GitLab aynı üçlü, ek olarak "yarı doğrusal" — önce
rebase, sonra --no-ff merge commit):
Merge commit (--no-ff) | Squash | Rebase + fast-forward | |
|---|---|---|---|
| Main'e giren | Dalın tüm commit'leri + 1 merge commit | Tek yeni commit | Dalın commit'leri yeniden yazılarak (yeni özetler) |
| Geçmiş şekli | Dallı; "hangi PR" merge commit'ten okunur | Düz; 1 PR = 1 commit | Düz; PR sınırı görünmez |
| Bisect / blame | Merge commit gürültüsü; --first-parent ile temiz | En temiz; ama büyük commit'te suçlu satır bulmak zor | Temiz, ince taneli |
| Geri alma | revert -m 1 (6. ders) | Tek revert | Commit sayısı kadar revert ya da aralık |
| Dalın commit temizliği | Yazara bağlı — "WIP", "typo" main'e girer | Önemsiz; hepsi erir | Şart — her commit main'de yaşayacak |
| Merge sonrası dal | -d ile silinir | -d reddeder, -D gerekir (3. ders) | Yerel dal eski özetlerde; sil, yeniden çek |
| İmzalı commit | Korunur | Yeni commit platform imzalar | Yeniden yazıldığı için yazar imzası düşer |
Karar ilkesi: küçük PR'larda squash — bir PR bir değişiklik birimidir, tek commit olarak main'e girer, tek revert ile geri gelir, PR açıklaması commit mesajı olur. Büyük ama iyi kürate edilmiş PR'larda (6. dersin interactive rebase'iyle temizlenmiş, her commit'i kendi başına anlamlı) rebase-ff ya da --no-ff merge; ilki düz, ikincisi "PR sınırı" bilgisini saklar. Kıdem tuzağı: squash, uzun ömürlü dallar arasında tekrar tekrar kullanılırsa (develop'a squash, sonra develop'tan tekrar dal, tekrar squash) Git aynı değişiklikleri "yeni" sanır ve her seferinde çatışma üretir — squash, kısa ömürlü dalın main'e girişi için vardır, GitFlow'un develop↔release trafiği için değil. Bir ekipte tek seçenek zorlanır: platform ayarında diğer ikisi kapatılır (GitHub: "Allow squash merging" tek başına), yoksa geçmiş kişiye göre değişen bir karışım olur.
08Dal koruma, isimlendirme, monorepo
Strateji yazılı kural olarak kalırsa unutulur; sunucuya dal koruma olarak yazılırsa uygulanır (4. dersin "force yasağı" senedinin sunucu tarafı; ayrıntı 8. derste): main'e doğrudan push yok, yalnız PR; force push yok; zorunlu durum kontrolleri (CI yeşil); en az N onay; isteğe bağlı doğrusal geçmiş (yalnız squash/rebase) ve imzalı commit. Bu kurallar yöneticilere de uygulanır — "admin istisnası" kuralın yokluğudur.
İsimlendirme, stratejinin görünen yüzüdür ve otomasyona girdi olur:
tür/is-kaydi-kisa-ad — feature/BAS-142-son-gun-kurali,
fix/BAS-201-saat-dilimi, release/1.4. Tür öneki hangi dalın ne
olduğunu grafta söyler, iş kaydı numarası PR'ı iş yönetimine otomatik bağlar (8. ders),
kalanı insana hitap eder. 3. dersin ref kısıtları geçerlidir: boşluk, iki nokta,
.. yok. Ekip bu kalıbı sunucu tarafında da zorlayabilir (dal adı deseni
kuralı).
Monorepo notu: bazı kurumlar tüm projeleri tek depoda tutar (API, web, ortak
kütüphaneler). Strateji tercihini değiştirmez ama iki şeyi zorlar: trunk-based dışında
bir model monorepo'da hızla kilitlenir (bir sürüm dalı = tüm projeler donar), ve CI
"hangi klasör değişti" bilgisine göre yalnız etkilenen projeleri koşturmalıdır (18. hat
yol filtreleri). Git tarafında git sparse-checkout yalnız ilgilendiğin
klasörleri çalışma alanına indirir, git log -- klasor/ proje bazlı geçmiş
verir, kod sahipliği klasör başına tanımlanır (8. ders CODEOWNERS). Bir depoya girip
git log --graph --oneline --all | head -50 ile hangi stratejinin uygulandığını
okuyabilmek — uzun yaşayan develop çizgisi, düzenli tag'ler, tek düz çizgi — alışkanlık
hâline getirilecek bir teşhis becerisidir.
09Hangi durumda hangisi: karar tablosu ve DORA bağı
| Durum | Trunk-based | GitHub Flow (+ release dalı) | GitFlow |
|---|---|---|---|
| Dağıtım sıklığı | Günde çok kez | Günlük–haftalık | Haftalar–aylar |
| Sürüm modeli | Tek canlı sürüm (SaaS, iç servis) | Tek canlı sürüm; ara sıra sürüm dalı | Çoklu desteklenen sürüm, paketlenmiş ürün |
| Test/CI olgunluğu | Şart: hızlı CI, güvenilir testler | PR'da CI yeterli | Release evresinde elle test toleransı var |
| Ekip boyutu | Her boyut; büyükte bayrak disiplini şart | Küçük–orta | Büyük, dağınık, sürüm yöneticisi olan |
| Onay/dağıtım penceresi | Bayrakla: kod erken girer, açılış onayla | Release dalı + tag ile pencereye uyar | Release dalı doğal onay evresi |
| Ana risk | Bayrak borcu, disiplinsiz commit | Çoklu sürüm desteği yok | Unutulan çift merge, geç entegrasyon |
Kamu kurumu senaryosu. Şartnameyle alınmış bir sistem, kabul testi (UAT) ortamı,
değişiklik kurulunun onayladığı dağıtım pencereleri (ayda iki), tek üretim ortamı, kurum
içi 8 kişilik ekip. GitFlow'un çoklu sürüm desteği gereksizdir, saf GitHub Flow'un
"merge = dağıt" varsayımı pencereye uymaz. Uygun cevap ortadadır: trunk-based/GitHub
Flow + pencere başına release dalı — herkes kısa dallardan PR ile main'e girer, pencere
öncesi main'den release/2026.09.2 kesilir ve UAT'ye çıkar, kabul edilen
düzeltmeler main'de yapılıp cherry-pick -x ile dala taşınır, pencere günü
dal tag'lenip dağıtılır. Bu, Microsoft'un Azure DevOps ekibinin "Release Flow" adıyla
belgelediği düzenin aynısıdır. Bitmemiş özellikler bayrak arkasında main'de bekler; UAT'de
açılıp üretimde kapalı kalabilir. Sözlüde bu senaryoyu "GitFlow kullanırım" diye kapatan
aday, çift merge'ü ve geç entegrasyonu üstlenmiş olur; gerekçeli hibrit cevap ayırt
edicidir.
DORA bağı. Dört metrik: dağıtım sıklığı, değişiklik için lead time (commit'ten üretime), değişiklik hata oranı, geri getirme süresi. Dal ömrü, lead time'ın doğrudan bileşenidir — dalda bekleyen kod üretime gitmeyen koddur; büyük dal büyük dağıtımdır, büyük dağıtım yüksek hata oranı ve uzun geri getirmedir. Strateji seçimi bu dört sayıyı hedeflemenin aracıdır; sayılar 18. hatta ölçülür.
10Mini alıştırma — iki strateji, aynı depo
Yaklaşık 20 dakika · 4. dersin bare deposu ve bir klon
- GitFlow provası.
developaç. İkifeature/dalı aç, develop'a--no-ffile birleştir.release/1.0kes, bir "sürüm numarası" commit'i at, hem main'e hem develop'a merge et, main'dev1.0.0annotated tag. Sonra main'denhotfix/1.0.1aç, düzelt, yalnız main'e merge et ve develop'ı unut.git log develop..main: düzeltme develop'ta yok — sonraki sürümde hata geri gelir. Şimdi develop'a da merge et. - Trunk-based provası. Yeni bir klonda yalnız main. Küçük bir fonksiyona
if (bayrak)ile yeni bir yol ekle, bayrak kapalı, main'e commit. İki commit daha.release/1.1kes ve tag'le. Main'de bir düzeltme commit'i at,cherry-pick -xile release'e taşı;git cherry main release/1.1çıktısını yorumla. Bayrağı açan tek satırlık commit'i at: "yayın" ile "dağıtım"ın ayrıldığını gör. - Üç düğme. Üç commit'li bir dalı üç kopyada üç biçimde main'e al:
merge --no-ff,merge --squash+ commit,rebase+merge --ff-only. Her kopyadagit log --graph --onelinevegit branch -d dal: hangisi reddetti, neden? - Teşhis. İki klonun
git log --graph --oneline --allçıktısını yan yana koy; hangi stratejinin uygulandığını grafın hangi özelliğinden anladığını üç maddeyle yaz. - Karar. 09. bölümdeki kamu senaryosu için bir sayfalık strateji kararı yaz: dallar, ömür, merge davranışı, hotfix akışı, gerekçe. Bu belge 12. düğümün A çıktısının taslağıdır.
11Kendini sına
GitFlow'un dalları nelerdir, akış nasıl işler? Hangi durumda uygundur ve gizli maliyeti nedir?
İki kalıcı dal: main (yalnız üretim sürümleri, her
commit tag'li) ve develop (sonraki sürümün entegrasyon dalı); üç geçici tür:
feature/* (develop'tan açılır, develop'a döner), release/*
(develop'tan kesilir, yalnız düzeltme alır, bitince hem main'e hem develop'a merge edilir
ve main'de tag'lenir), hotfix/* (main'den açılır, hem main'e hem develop'a
merge edilir). Uygun olduğu yer: paketlenip teslim edilen ürün, aynı anda birden fazla
desteklenen sürüm, sürüm arasında resmî dondurma/onay evresi. Gizli maliyeti: release ve
hotfix'in çift merge'ü — biri unutulursa üretimde düzeltilen hata sonraki sürümde geri
gelir; uzun ömürlü develop ve haftalarca yaşayan feature dalları geç entegrasyon ve büyük
çatışma üretir; main yalnız sürümlerde ilerlediği için sürekli dağıtımla uyumsuzdur.
Modelin yazarı 2020'de sürekli teslimat yapan ekiplere daha basit bir akış (GitHub Flow)
önermiştir.
Trunk-based development nedir? Haftalar sürecek bir iş günlük parçalarla main'e nasıl girer? Ön şartları nelerdir?
Tek kalıcı dal (trunk/main); herkes en az günde bir kez ona
commit gönderir — doğrudan ya da ömrü bir-iki günü geçmeyen kısa dallardan PR ile.
Büyük iş iki teknikle parçalanır: özellik bayrağı — yeni kod yolu main'e kapalı bir
anahtarın arkasında girer, yayın dağıtımdan ayrılır, kısmi/kademeli açılır, sorun çıkarsa
kod geri alınmadan kapatılır; bayrak türleri release/deney/işletim/yetki, her bayrak son
kullanma tarihli teknik borçtur ve bitince silinir. Soyutlamayla dallanma — büyük
değişim main'de adım adım: arayüz konur, çağıranlar taşınır, yeni uygulama bayrak
arkasında büyür, eski kaldırılır. Sürüm dalı yalnız kesim içindir; düzeltme main'de
yapılıp cherry-pick -x ile taşınır. Ön şartlar: dakikalar içinde koşan hızlı
CI, güvenilir test ağı (main her an dağıtılabilir), küçük atomik commit'ler, dalı
bekletmeyen hızlı kod incelemesi. DORA araştırmaları kısa dal ömrü ve az aktif dalı yüksek
performansla ilişkilendirir.
PR düğmesinin üç seçeneği (merge commit / squash / rebase) neyi değiştirir? Hangisini ne zaman seçersin; squash'ın tuzağı nedir?
Merge commit (--no-ff): dalın tüm commit'leri + bir
merge commit; dallı geçmiş, "hangi PR" merge commit'ten okunur, revert -m 1
ile geri alınır, bisect/blame'de gürültü (--first-parent yardım eder), dal
-d ile silinir. Squash: tek yeni commit; düz geçmiş, 1 PR = 1 commit, tek
revert, dal temizliği önemsiz; ama -d reddeder (-D gerekir) ve
büyük commit'te suçlu satır zor bulunur. Rebase + ff: commit'ler yeniden yazılarak
(yeni özetler) düz geçmişe girer, ince taneli bisect; her commit main'de yaşayacağı için
dal temizliği şart, yazar imzası düşer, yerel dal eski özetlerde kalır. Karar: küçük
PR'larda squash; iyi kürate edilmiş büyük PR'larda rebase-ff ya da PR sınırını saklamak
için --no-ff; ekipte tek seçenek platform ayarıyla zorlanır. Squash tuzağı: uzun ömürlü
dallar arasında tekrar tekrar squash (develop↔release trafiği) Git'in aynı değişiklikleri
yeni sanmasına ve her seferinde çatışmaya yol açar — squash, kısa ömürlü dalın main'e
girişi içindir.
Hotfix nasıl çıkarılır; "upstream first" ne demektir? Onaylı dağıtım pencereleri olan bir kamu kurumu için hangi stratejiyi önerirsin, neden?
İki okul: GitFlow'da hotfix main'den açılır, hem main'e hem
develop'a merge edilir. Upstream first (trunk-based/GitLab Flow): düzeltme önce main'de
yapılır, test edilir ve PR ile girer; sonra cherry-pick -x ile sürüm dalına
taşınır, dalda v1.4.1 annotated tag atılır, --follow-tags ile
push edilir; git cherry taşınmamış commit kaldı mı diye denetler. Gerekçesi:
düzeltme main'de olduğu için gelecek sürümde unutulamaz, sürüm dalı hep main'in alt
kümesidir; birden fazla desteklenen sürüm varsa her dala ayrı cherry-pick — destek
penceresi dal sayısını ve bakım maliyetini belirler. Kamu senaryosu (tek üretim, UAT,
ayda iki onaylı pencere, 8 kişi): GitFlow'un çoklu sürüm desteği gereksiz, saf GitHub
Flow'un "merge = dağıt"ı pencereye uymaz; öneri trunk-based/GitHub Flow + pencere başına
release dalı (Release Flow): kısa dallardan PR ile main, pencere öncesi main'den kesilen
release dalı UAT'ye, düzeltmeler main'de yapılıp cherry-pick ile dala, pencere günü tag +
dağıtım; bitmemiş özellikler bayrak arkasında. Gerekçe: geç entegrasyon ve çift merge
maliyeti yok, onay evresi release dalında doğal olarak var.
12Sınav köşesi
Yazılıda nasıl sorulur
(1) GitFlow'daki dal türlerini ve her birinin nereden açılıp nereye birleştiğini yazınız. (2) Trunk-based development nedir; feature branch modelinden farkı nedir? (3) Feature flag (özellik bayrağı) nedir, ne işe yarar? (4) Hotfix nasıl çıkarılır; release dalına nasıl taşınır? (5) Squash merge ile merge commit arasındaki fark nedir? (6) Uzun ömürlü dalların sakıncaları nelerdir? (7) Korumalı dal (protected branch) ne demektir? (8) Sürekli dağıtım yapan bir ekip için hangi branching stratejisi uygundur, neden? (9) Sürüm numaralandırmada SemVer kuralları nelerdir? (10) DORA metrikleri nelerdir?
Sözlüde nasıl anlatılır — 2 dakikalık taslak
Düzen: (1) Çerçeve — "Strateji, dalların nasıl düzenlendiği, ne kadar yaşadığı ve main'e nasıl girdiğinin ekip kararıdır; hepsi tek eksende sıralanır: entegrasyon ne kadar sık." (2) Üçlü — "GitFlow çoklu sürüm ve resmî dondurma için; bedeli çift merge ve geç entegrasyon. GitHub Flow main'i her an dağıtılabilir tutar. Trunk-based günlük entegrasyon, kısa dal, özellik bayrağı; ön şartı hızlı CI ve güvenilir test." (3) Sürüm — "Sürümü main'den keser, annotated tag atarım; düzeltmeyi main'de yapıp cherry-pick -x ile sürüm dalına taşırım — upstream first, düzeltme gelecek sürümde unutulmaz." (4) Merge davranışı — "Küçük PR'larda squash, kürate edilmiş büyük PR'larda rebase ya da --no-ff; ekipte tek seçenek, platform ayarıyla." (5) Kıdem vuruşu — "Onaylı dağıtım pencereli bir kurumda trunk-based + pencere başına release dalı kurarım: kod erken girer, bayrak arkasında bekler, UAT release dalında, hotfix cherry-pick ile. Dal ömrü DORA lead time'ının doğrudan bileşenidir; strateji o sayıları hedeflemenin aracıdır."
