Birleştirmek veya merge etmek — Git'te iki dalı birleştirme, değişiklikleri bir daldan diğerine aktarma eylemidir. Modern geliştirmede merge, bir özellik dalını projenin ana dalına entegre etmenin standart yoludur. GitHub Octoverse 2024'e göre, günlük olarak 15 milyondan fazla merge gerçekleştirilmektedir. Merge, birden fazla geliştiricinin çalışmalarını tek bir üründe birleştirmeye olanak tanıyan işbirlikçi çalışmanın temel mekanizmasıdır.
Ana Noktalar
Git'te merge, iki veya daha fazla geliştirme geçmişini birleştirme işlemidir. Bir geliştirici bir dalı birleştirdiğinde, Git otomatik olarak ortak atayı (base commit) bulur ve her iki daldaki değişiklikleri içeren yeni bir merge commit oluşturur. Three-way merge, üç durumu karşılaştıran standart algoritmadır: ortak ata, birinci dal ve ikinci dal.
Merge süreci git merge komutuyla başlar. Git, dalların ayrışma noktasını belirler ve kaynak daldan hedef dala sırayla değişiklikleri uygular. Değişiklikler çakışmazsa, Git ayarlara bağlı olarak fast-forward gerçekleştirir veya merge commit oluşturur. Fast-forward, hedef dalın kaynak dalın commit'lerine basitçe hareket ettiği bir senaryodur.
# Hedef dala geç ve birleştir
git checkout main
git merge feature/payment-module
# Açık no-fast-forward ile birleştir
git merge --no-ff feature/payment-module
# Çakışmalar çok karmaşıksa merge'i iptal et
git merge --abort
--no-ff bayrağı (no fast-forward), fast-forward mümkün olsa bile merge commit oluşturulmasını zorlar. Bu, değişikliklerin ayrı bir dalda yapıldığı bilgisini korur. Birçok ekip, dal geçmişini açık bir şekilde korumak için bu yaklaşımı tercih eder.
Git'te her biri belirli bir senaryo için uygun olan üç ana dal birleştirme stratejisi vardır. Strateji seçimi, ekibin kültürüne ve proje geçmişinin temizliği gereksinimlerine bağlıdır.
| Strateji | Sonuç | Ne zaman kullanılır |
|---|---|---|
| Standard merge | merge commit + tam geçmiş | tam geçmişe değer veren ekipler |
| Squash merge | tek commit, sıkıştırılmış geçmiş | çok sayıda küçük commit içeren özellik dalları |
| Rebase merge | doğrusal geçmiş, merge commit yok | kişisel özellik dalları, PR oluşturmadan önce |
Standard merge, iki ebeveynli bir merge commit oluşturur. Tam geçmiş korunur, ancak dal grafiği daha karmaşık hale gelir. Squash merge, bir özellik dalının tüm commit'lerini tek bir commit'te birleştirir ve hedef dalın üzerine uygular — geçmiş doğrusal ve temiz hale gelir, ancak ara aşamalar hakkındaki bilgiler kaybolur.
Rebase, tam teşekküllü bir merge olmasa da aynı sonucu elde eder — bir daldaki değişiklikler başka bir dalın üzerine taşınır. Fark, geçmişin yeniden yazılmasıdır: özellik dalının commit'leri, hedef dalın son commit'inin üzerinde yeniden oluşturulur. Bu mükemmel doğrusal bir geçmiş sağlar, ancak gönderirken force push gerektirir.
Merge çakışması, bir dosyanın aynı satırları iki dalda değiştirildiğinde ortaya çıkar. Git hangi sürümün korunacağını otomatik olarak belirleyemez ve geliştiricinin müdahalesini gerektirir. Çakışmalar dosyalarda özel işaretleyicilerle gösterilir: <<<<<<<, =======, >>>>>>>.
Çakışma çözüm süreci birkaç adım içerir. İlk olarak, geliştirici çakışan dosyayı açar ve gerekli değişiklikleri manuel olarak seçer. Sadece bir sürümü seçmek değil, her iki değişikliğin mantığını anlamak ve doğru kararı vermek önemlidir. Dosyayı düzenledikten sonra, çakışma işaretleyicileri kaldırılır ve değişiklikler git add ile staging alanına eklenir.
# Çakışan dosyaların listesini görüntüle
git status
# mergetool'u başlat (ör. VS Code, IntelliJ)
git mergetool
# Tüm çakışmaları çözdükten sonra
git add .
git merge --continue
# Veya merge'i tamamen iptal et
git merge --abort
Görsel merge araçlarının kullanımı çakışma çözümünü önemli ölçüde hızlandırır. VS Code, IntelliJ IDEA ve GitKraken, üç panelli arayüzler sağlar: mevcut dal, gelen dal ve sonuç. git mergetool aracı, çakışan her dosya için yapılandırılmış düzenleyiciyi otomatik olarak açar.
Karmaşık çakışmalardan kaçınmanın en iyi yolu, özellik dalının ana dalla düzenli senkronizasyonudur. Bir geliştirici günde bir kez main'i kendi dalına merge ederse, çakışmalar küçük ve kolayca çözülebilir olacaktır. Değişiklikleri bir hafta boyunca biriktirmek, yüksek hata riskiyle karmaşık çakışmaları garanti eder.
Rebase ve merge, değişiklikleri birleştirmenin iki yoludur ve aralarındaki seçim genellikle ekiplerde tartışmalara neden olur. Rebase, geçmişi yeniden yazarak commit'leri bir daldan diğerinin üzerine taşır. Merge, dal geçmişini koruyarak yeni bir merge commit oluşturur. Her yaklaşımın avantajları ve sınırlamaları vardır.
Rebase, bir geliştirici yerel özellik dalında çalışırken ve Pull Request oluşturmadan önce temiz bir doğrusal geçmiş istediğinde uygundur. Rebase'den sonra, tüm commit'ler gereksiz merge commit'leri olmadan sıralı olarak düzenlenir. Ancak rebase, force push gerektirir ve aynı anda birden fazla kişinin çalıştığı dallara uygulanamaz.
Git'in altın kuralı: zaten ortak depoya push edilmiş commit'lerde rebase kullanmayın. Bu, ortak daldaki geçmişin değişmeden kalmasını ve diğer geliştiricilerin yinelenen veya kaybolmuş commit'lerle karşılaşmamasını sağlar. Özellik dalını ana dalla birleştirmek için Pull Request aracılığıyla merge kullanın.
Doğru merge süreci, istikrarlı geliştirmenin temelidir. Modern ekip çalışmasında, birleştirme konsol üzerinden değil, GitHub'da Pull Request veya GitLab'da Merge Request aracılığıyla yapılır. Bir PR, kod incelemesi, otomatik CI kontrollerinden geçer ve ancak ondan sonra ana dalla birleştirilir.
İlk uygulama — yalnızca tüm kontroller geçtikten sonra birleştirin. CI pipeline'ı projeyi derlemeli, testleri çalıştırmalı ve kod kalitesini doğrulamalıdır. En az bir kontrol başarısız olursa, merge engellenir. Modern platformlar (GitHub, GitLab) yerleşik korumaya sahiptir: branch protection rules, CI başarısız olduğunda otomatik olarak merge'i engeller.
İkinci uygulama — asla bozuk kodu birleştirmeyin. Merge'den önce, geliştirici değişikliklerinin derlemeyi bozmadığından ve mevcut işlevselliği geriletmediğinden emin olmalıdır. Bunun için otomatik testler ve kod incelemesi vardır.
Üçüncü uygulama — merge'den sonra özellik dallarını temizleyin. Zaten birleştirilmiş bir dal silinmelidir. Bu, karışıklığı ve depoda dağınıklığı önler. GitHub, bir PR birleştirildikten sonra otomatik olarak dalı silmeyi önerir ve depo ayarları otomatik silme için yapılandırılabilir.
Sıkça Sorulan Sorular
Merge, iki Git dalını birleştirmektir. Bir daldaki değişiklikler, üç yönlü birleştirme (three-way merge) yoluyla diğerine aktarılır. Sonuç, iki ebeveyn commit'i olan yeni bir merge commit'inde kaydedilir. Merge commit, hangi dalların birleştirildiği hakkındaki bilgileri korur.
Merge yeni bir merge commit oluşturur, dal geçmişini korur. Rebase, merge commit oluşturmadan commit'leri başka bir dalın üzerine taşıyarak geçmişi yeniden yazar. Rebase doğrusal geçmiş sağlar ancak force push gerektirir. Merge ortak dallar için daha güvenlidir, rebase kişisel dallar için daha iyidir.
Çakışan dosyayı açın, <<<<<<<, ======= ve >>>>>>> işaretleyicilerini bulun, gerekli değişiklikleri seçin ve işaretleyicileri kaldırın. Dosyayı git add ile ekleyin ve git merge --continue ile merge'i tamamlayın. VS Code veya IntelliJ IDEA'da görsel çözüm için git mergetool kullanın.
Pull Request (veya Merge Request), özellik dalını projenin ana dalına birleştirirken zorunludur. Bir PR, meslektaşların kod incelemesinden ve otomatik CI kontrollerinden geçer. Bu, modern geliştirmenin standardıdır. Çoğu projede ana dala doğrudan push yasaktır.
Squash merge, birleştirmeden önce özellik dalının tüm commit'lerini tek bir commit'te birleştirir. Bu, ara taslak commit'ler olmadan ana dalın temiz bir geçmişini sağlar. Özellik dalı çok sayıda yardımcı commit (wip, fixes) içerdiğinde ve geçmişte tüm ara adımları korumak gerekmediğinde squash merge kullanın.
Özet
Anahtar teslim bir mobil uygulama geliştireceğiz
IT Sectr, 2017'den beri girişimler ve işletmeler için iOS ve Android uygulamaları oluşturmaktadır. Size danışmanlık yapacak ve en iyi çözümü önereceğiz.
Ayrıca okuyun