Gitflow AVH ile Otomatik Branch Yönetimi

Ekipte on beş kişi varken “main’e direkt push attım, bir şey olmaz” diyen geliştirici sayısını hatırlamak istemiyorum. O günlerin bitmesi için bir şeyler yapmak gerekiyordu ve gitflow-avh tam o noktada hayatıma girdi.

Standart git flow kurulumunu biliyorsunuzdur: Atlassian ve nvie’nin klasik yaklaşımı. Ama AVH (A Virtual Home) fork’u çok daha aktif geliştirilen, hook desteği güçlendirilmiş ve birçok edge case’i daha temiz çözen versiyonu. Bugün bunu ele alacağız, hem kurulumdan hem de gerçek dünya iş akışlarından bahsedeceğiz.

Gitflow AVH Nedir, Neden Önemseyelim?

Git flow modeli temelde şu fikre dayanır: farklı amaçlar için farklı branch tipleri kullanırsınız. main (ya da master) production’da olan kodu temsil eder. develop bir sonraki release için birikmekte olan kodu barındırır. feature/ branch’leri yeni özellikler için açılır, release/ branch’leri release hazırlığı için, hotfix/* branch’leri ise kritik production düzeltmeleri için kullanılır.

AVH fork’unun orijinalden farkı şu noktalarda öne çıkıyor:

  • Hook sistemi: Her branch işlemi öncesi ve sonrası hook çalıştırabiliyorsunuz
  • Aktif maintenance: Orijinal repo yıllardır güncellenmedi, AVH hâlâ aktif
  • Daha iyi hata mesajları: Özellikle conflict durumlarında çok daha anlaşılır çıktılar
  • Squash merge desteği: Feature tamamlarken squash yapabilme seçeneği

Kurulum

Kurulum birkaç farklı yoldan yapılabiliyor. Sisteminize göre:

# macOS - Homebrew
brew install git-flow-avh

# Ubuntu/Debian
apt-get install git-flow

# Fedora/RHEL
dnf install gitflow

# Manuel kurulum (tüm sistemler için)
wget -q https://raw.githubusercontent.com/petervanderdoes/gitflow-avh/develop/contrib/gitflow-installer.sh
chmod +x gitflow-installer.sh
sudo ./gitflow-installer.sh install stable

Kurulum sonrası versiyonu kontrol edin. AVH kuruluysa çıktıda “AVH Edition” yazması gerekir:

git flow version
# 1.12.3 (AVH Edition)

Repo Başlatma ve Konfigürasyon

Mevcut bir repoda git flow başlatmak:

cd /path/to/your/repo
git flow init

Bu komut size bir dizi soru sorar. Branch isimlerini, prefix’leri ayarlarsınız. Ekibinizle standartlaştırmak için bu değerleri -d flag’i ile default olarak kabul edebilir ya da her şeyi elle belirtebilirsiniz:

git flow init -d
# Branch adları için default değerleri kullanır:
# Production branch: master (ya da main)
# Development branch: develop  
# Feature prefix: feature/
# Bugfix prefix: bugfix/
# Release prefix: release/
# Hotfix prefix: hotfix/
# Support prefix: support/
# Version tag prefix: (boş)

Eğer yeni başlayan bir projeyse ve main kullanmak istiyorsanız:

git flow init
# Branch name for production releases: [master] main
# Branch name for "next release" development: [develop] develop
# Feature branches? [feature/]
# Bugfix branches? [bugfix/]
# Release branches? [release/]
# Hotfix branches? [hotfix/]
# Support branches? [support/]
# Version tag prefix? []

Bu ayarlar .git/config dosyasına yazılır. Ekip genelinde aynı konfigürasyonu kullanmak için bu değerleri paylaşabilir ya da bir setup script’i yazabilirsiniz.

Feature Branch Yönetimi

Günlük iş akışının merkezinde feature branch’leri var. Klasik senaryoyu düşünelim: sprint başladı, size “kullanıcı profil sayfası” görevi düştü.

# Feature branch aç
git flow feature start kullanici-profil-sayfasi

# Bu komut arka planda şunu yapar:
# git checkout develop
# git checkout -b feature/kullanici-profil-sayfasi

Geliştirme sürecinde normal git kullanıyorsunuz. Commit’ler, push’lar, her şey olağan. Birden fazla kişi aynı feature üzerinde çalışıyorsa:

# Feature'ı remote'a yayınla
git flow feature publish kullanici-profil-sayfasi

# Takım arkadaşı bu feature'ı çeksin
git flow feature track kullanici-profil-sayfasi

Feature tamamlandığında:

# Feature'ı bitir ve develop'a merge et
git flow feature finish kullanici-profil-sayfasi

# Squash merge istiyorsanız (temiz history için)
git flow feature finish --squash kullanici-profil-sayfasi

finish komutu şunları yapar: feature branch’i develop’a merge eder, feature branch’i siler, develop’a checkout yapar. Temiz, otomatik, hata payı az.

Bir gerçek dünya nüansını paylaşayım: uzun süren feature’larda develop ile aranız açılır. Bunu yönetmek için düzenli rebase yapın:

git flow feature rebase kullanici-profil-sayfasi
# develop'daki son değişiklikleri feature branch'inize taşır

Release Branch Yönetimi

Sprint sonu geldi, bir sürüm çıkarmak üzeresiniz. Develop branch’indeki kod test edildi, QA onayladı.

# Release branch aç
git flow release start 2.4.0

# Bu komut:
# git checkout develop
# git checkout -b release/2.4.0

Release branch açıldığında artık bu branch’e sadece bug fix’ler gider. Yeni feature kesinlikle eklenmez. Bu noktada QA ekibi üzerinde test yapabilir, versiyon numaraları güncellenir, changelog yazılır.

# Versiyon dosyasını güncelle
echo "2.4.0" > VERSION
git add VERSION
git commit -m "chore: bump version to 2.4.0"

# Release'i remote'a yayınla (QA erişebilsin diye)
git flow release publish 2.4.0

Herkes hazır, release yapılacak:

git flow release finish 2.4.0

Bu komut arkada oldukça fazla iş yapıyor:

  • release/2.4.0 branch’ini main’e merge eder
  • “2.4.0” tag’i oluşturur
  • release/2.4.0 branch’ini develop’a merge eder
  • release branch’ini siler

Tag oluştururken mesaj girmek için editor açılır. Tag mesajınızı buraya yazın, changelog özetini koyun.

# Tag'leri remote'a push etmeyi unutmayın!
git push origin main
git push origin develop
git push --tags

Bu adımı otomatize etmek için bir script:

#!/bin/bash
# release-finish.sh
VERSION=$1

if [ -z "$VERSION" ]; then
    echo "Kullanim: ./release-finish.sh <versiyon>"
    exit 1
fi

git flow release finish -m "Release $VERSION" "$VERSION"
git push origin main
git push origin develop  
git push origin --tags

echo "Release $VERSION tamamlandi ve push edildi."

Hotfix Yönetimi

Gece yarısı production’da kritik bir bug bulundu. Müşteriler etkileniyor. Panik yok, hotfix var.

# main'den hotfix branch aç
git flow hotfix start 2.4.1

# Bu komut main'den branch açar, develop'tan değil
# Çünkü develop'ta henüz tamamlanmamış özellikler olabilir

Düzeltmeyi yapın, test edin:

# Hatayı düzelt
vim src/payment/processor.py
git add src/payment/processor.py
git commit -m "fix: null pointer exception in payment processor"

# Hotfix'i bitir
git flow hotfix finish 2.4.1

Hotfix finish komutu:

  • hotfix branch’ini main’e merge eder
  • “2.4.1” tag’i oluşturur
  • hotfix branch’ini develop’a da merge eder (çok önemli!)
  • hotfix branch’ini siler

Develop’a da merge etmesi kritik. Yoksa bir sonraki release’de aynı bug tekrar çıkar.

Eğer o anda açık bir release branch’i varsa, develop yerine oraya merge eder. Bu akıllıca bir davranış.

Hook Sistemi ile Otomasyon

AVH’nin en güçlü özelliği hook sistemi. Klasik git hook’larının yanı sıra, her git flow komutuna özel hook’lar tanımlayabiliyorsunuz.

Hook dosyaları .git/hooks/ altında aşağıdaki isimlendirme kuralıyla oluşturulur:

  • gitflow-pre-feature-start: Feature açılmadan önce
  • gitflow-post-feature-start: Feature açıldıktan sonra
  • gitflow-pre-feature-finish: Feature kapatılmadan önce
  • gitflow-post-feature-finish: Feature kapatıldıktan sonra
  • gitflow-pre-release-start: Release açılmadan önce
  • gitflow-post-release-finish: Release tamamlandıktan sonra
  • gitflow-pre-hotfix-finish: Hotfix kapatılmadan önce

Pratik bir örnek: Feature finish öncesi test suite çalıştıralım.

#!/bin/bash
# .git/hooks/gitflow-pre-feature-finish

FEATURE_NAME=$1
ORIGIN=$2
MASTER_BRANCH=$3
DEVELOP_BRANCH=$4

echo "Feature '$FEATURE_NAME' kapatılmadan once testler calistiriliyor..."

# Test suite'i çalıştır
if ! npm test; then
    echo "HATA: Testler basarisiz! Feature finish iptal edildi."
    exit 1
fi

echo "Testler basarili, devam ediliyor."
exit 0

Başka bir hook örneği: Release başlamadan önce develop branch’inin CI’dan geçip geçmediğini kontrol edelim. Bu örnek GitHub API kullanıyor:

#!/bin/bash
# .git/hooks/gitflow-pre-release-start

REPO_OWNER="myorg"
REPO_NAME="myapp"
BRANCH="develop"

echo "develop branch CI durumu kontrol ediliyor..."

STATUS=$(curl -s 
  -H "Authorization: token $GITHUB_TOKEN" 
  "https://api.github.com/repos/$REPO_OWNER/$REPO_NAME/commits/$(git rev-parse develop)/check-runs" 
  | python3 -c "import sys,json; data=json.load(sys.stdin); print('ok' if all(r['conclusion']=='success' for r in data['check_runs']) else 'fail')")

if [ "$STATUS" != "ok" ]; then
    echo "HATA: develop branch CI kontrolunden gecemiyor!"
    echo "Once pipeline sorunlarini cozun."
    exit 1
fi

echo "CI kontrolu basarili."
exit 0

Bugfix Branch’leri

AVH Edition’ın getirdiği ve az bilinen özelliklerden biri bugfix branch’leri. Feature branch’lerinin develop’tan açılmasına karşın, bugfix branch’leri develop üzerindeki bug’lar için kullanılır. Release branch’lerinde çıkan sorunlar için de kullanılabilir.

# Develop'ta bulunan bir bug için
git flow bugfix start login-validation-error

# Düzeltmeyi yap
git add .
git commit -m "fix: email validation regex hatalı karakter setini reddediyordu"

# Bitir
git flow bugfix finish login-validation-error

Hotfix’ten farkı: hotfix production’a (main’e) giderken, bugfix develop’a gider. Kavramsal ayrım önemli, ekip içinde bu terminolojiyi netleştirmek faydalı.

Ekip İçin Konfigürasyon Standardizasyonu

On kişilik bir ekipte herkesin aynı git flow konfigürasyonunu kullanması gerekiyor. Bunun için repo içine bir setup script’i koymak en temiz yol:

#!/bin/bash
# scripts/setup-gitflow.sh

echo "Git flow AVH konfigurasyonu yapiliyor..."

git config gitflow.branch.master main
git config gitflow.branch.develop develop
git config gitflow.prefix.feature feature/
git config gitflow.prefix.bugfix bugfix/
git config gitflow.prefix.release release/
git config gitflow.prefix.hotfix hotfix/
git config gitflow.prefix.support support/
git config gitflow.prefix.versiontag v

# Hook'ları kur
HOOKS_DIR=".git/hooks"
SCRIPTS_DIR="scripts/git-hooks"

for hook in "$SCRIPTS_DIR"/*; do
    hook_name=$(basename "$hook")
    cp "$hook" "$HOOKS_DIR/$hook_name"
    chmod +x "$HOOKS_DIR/$hook_name"
    echo "Hook kuruldu: $hook_name"
done

echo "Kurulum tamamlandi!"
echo "git flow version: $(git flow version)"

Bu script’i repo’ya ekleyin, README’de belirtin: “Projeye başlamadan önce ./scripts/setup-gitflow.sh çalıştırın.”

CI/CD Pipeline ile Entegrasyon

GitLab CI örneği üzerinden gidelim. Branch naming convention’ınızı pipeline’a yansıtmak kritik:

# .gitlab-ci.yml
stages:
  - test
  - build
  - deploy

test:
  stage: test
  script:
    - npm install
    - npm test
  rules:
    - if: '$CI_COMMIT_BRANCH =~ /^feature//'
    - if: '$CI_COMMIT_BRANCH =~ /^bugfix//'
    - if: '$CI_COMMIT_BRANCH == "develop"'

build-staging:
  stage: build
  script:
    - docker build -t myapp:$CI_COMMIT_SHORT_SHA .
    - docker push myapp:$CI_COMMIT_SHORT_SHA
  rules:
    - if: '$CI_COMMIT_BRANCH == "develop"'

deploy-staging:
  stage: deploy
  script:
    - kubectl set image deployment/myapp myapp=myapp:$CI_COMMIT_SHORT_SHA -n staging
  environment:
    name: staging
  rules:
    - if: '$CI_COMMIT_BRANCH == "develop"'

deploy-production:
  stage: deploy
  script:
    - kubectl set image deployment/myapp myapp=myapp:$CI_COMMIT_TAG -n production
  environment:
    name: production
  rules:
    - if: '$CI_COMMIT_TAG =~ /^v[0-9]+.[0-9]+.[0-9]+$/'
  when: manual

Bu konfigürasyonla: feature ve bugfix branch’leri sadece test çalıştırır, develop’a merge production’a gitmez staging’e gider, tag push edildiğinde production deploy tetiklenir (manuel onay ile).

Sık Karşılaşılan Sorunlar

Merge conflict feature finish sırasında: Feature çok uzun sürdüyse ve develop ilerledi ise finish sırasında conflict çıkabilir. Git flow işlemi durdurur, sizi conflict’i çözmeye bırakır. Çözdükten sonra:

git add .
git commit
git flow feature finish kullanici-profil-sayfasi

Yanlışlıkla develop’a direkt push: Bu olur. Hook ile önlemek için:

#!/bin/bash
# .git/hooks/pre-push

BRANCH=$(git symbolic-ref HEAD | sed 's!refs/heads/!!')
PROTECTED="develop main master"

for p in $PROTECTED; do
    if [ "$BRANCH" = "$p" ]; then
        echo "HATA: '$BRANCH' branch'ine direkt push yapılamaz!"
        echo "Feature/release/hotfix workflow'unu kullanın."
        exit 1
    fi
done
exit 0

Tag push unutma: Release finish sonrası tag’ler local’de kalır. Bunu otomatize etmek için post-release hook kullanın ya da yukarıdaki release-finish.sh script’ini standart hale getirin.

Sonuç

Gitflow AVH, git’in üzerine bir iş akışı standardı oturtuyor ve bunu araçsallaştırıyor. Tek başına kullanıldığında bile branch isimlerini tutarlı tutuyor, merge sıralarını doğru yapıyor, tag’leri oluşturuyor. Ama asıl gücü hook sistemiyle ortaya çıkıyor: testleri otomatik çalıştırıyorsunuz, CI durumunu kontrol ediyorsunuz, bildirim gönderiyorsunuz.

Beş kişilik bir startup’ta overkill olabilir mi? Belki. Ama on kişinin üzerine çıktığınız anda, ya bir konvansiyonunuz olur ya da sürekli “kim neyi nereye push etti” tartışması yaşarsınız. Gitflow AVH o konvansiyonu hem tanımlıyor hem de zorluyor.

Hook’ları mevcut toolchain’inizle entegre edin, CI/CD pipeline’ınızı branch naming convention’ına göre yapılandırın ve setup scriptini repo’ya koyun. Bir ay sonra kimse “acaba bu değişikliği nereye göndereceğim” diye sormaz olur. O zihinsel yükü kaldırmanın değeri, kurulum süresinin çok ötesinde.

Bir yanıt yazın

E-posta adresiniz yayınlanmayacak. Gerekli alanlar * ile işaretlenmişlerdir