Geliştiriciler arasında takımların main branch’teki en son değişikliklerle nasıl güncel kalması gerektiği konusunda yaygın bir tartışma var. Bu soru genellikle şu durumda ortaya çıkar: Biri yeni bir branch üzerinde çalışır, iş bitip birleştirmeye hazır olduğunda main branch bu arada değişmiştir ve çalışma branch’i güncel değildir, şimdi merge conflict’leri oluşmuştur.
Elbette birleştirmeden önce bunların çözülmesi gerekiyor. Ama soru şu: Bu durum nasıl çözülmeli? main branch’i çalışma branch’ine merge mi etmeliyiz? Yoksa çalışma branch’ini en son main branch üzerine rebase mi yapmalıyız?
Bence bu sorunun tek bir doğru cevabı var. Deneyimlerime göre, bu konu etrafında bu kadar çok tartışma çıkmasının temel nedeni, merge ile rebase’in bu bağlamda birbirinden nasıl farklı olduğu konusunda çok fazla yanlış anlama olması ve genel olarak rebase’in ne olduğunun yeterince anlaşılmaması.
Bu yüzden takımım için konuyu açıklığa kavuşturmaya çalışan bir SSS oluşturdum. Paylaşayım:
Merge nedir?
Farklı bir branch’teki tüm değişiklikleri mevcut branch’e birleştiren bir commit.
Rebase nedir?
Mevcut branch’teki tüm commit’lerin farklı bir temel commit üzerine yeniden uygulanması.
Merge ile rebase arasındaki temel farklar nelerdir?
mergesadece bir yeni commit oluşturur.rebasegenellikle birden fazla commit oluşturur (mevcut branch’teki commit sayısı kadar).mergeyeni bir commit üretir (merge-commit denen şey).rebasesadece mevcut commit’leri taşır.
Hangi durumlarda merge kullanmalıyız?
Dallanmış bir branch’teki değişiklikleri temel branch’e geri eklemek istediğinde merge kullan.
Bunu genellikle GitHub gibi platformlarda Pull/Merge Request’lerdeki “Merge” butonuna tıklayarak yaparsın.
Hangi durumlarda rebase kullanmalıyız?
Temel branch’teki değişiklikleri dallanmış bir branch’e eklemek istediğinde rebase kullan.
Bunu genellikle main branch’te bir değişiklik olduğunda work branch’lerinde yaparsın.
Neden temel branch’teki değişiklikleri çalışma branch’ine eklemek için merge kullanmamalıyız?
Git geçmişi birçok gereksiz merge commit’i içerecektir. Çalışma branch’inde birden fazla merge gerektiyse, çalışma branch’inde gerçek commit’lerden daha fazla merge commit’i bile olabilir!
Bu, Git’in tasarım felsefesini bozan bir döngü oluşturur ve Git geçmişinin herhangi bir görselleştirmesinde sorunlara yol açar.
Bir nehir düşün (mesela “Nil”). Su bir yönde akıyor (Git geçmişindeki zaman yönü). Ara sıra nehirden ayrılan kollar olduğunu ve bu kolların çoğunun nehre geri döndüğünü hayal et. Bir nehrin akışı doğal olarak böyle görünebilir. Mantıklı.
Ama sonra bu nehrin küçük bir kolunu düşün. Sonra bir şekilde, nehir kola akar ve kol oradan devam eder. Nehir artık teknik olarak ortadan kaybolmuştur, artık koldadır. Ama sonra bir şekilde, sihirli bir şekilde, o kol nehre geri birleşir. Hangi nehir diye sorarsın? Bilmiyorum. Nehrin artık kolda olması gerekiyordu, ama bir şekilde hâlâ var olmaya devam ediyor ve kolu nehre birleştirebiliyorum. Yani nehir nehrin içinde. Pek mantıklı değil.
Tam olarak temel branch’i work branch’ine merge edip sonra work branch’i bitince tekrar temel branch’e merge ettiğinde olan şey budur. Zihinsel model bozulmuş olur. Ve bu yüzden pek yardımcı olmayan bir branch görselleştirmesiyle karşılaşırsın.
merge kullanıldığında örnek Git Geçmişi:

merge kullanıldığında örnek Git Geçmişi
Merge branch 'main' into … ile başlayan birçok commit’e dikkat et (sarı kutularla işaretlenmiş). Rebase kullansaydın bunlar hiç var olmazdı (orada sadece pull request merge commit’leri olur). Ayrıca birçok görsel branch birleşme döngüsüne dikkat et (main’den work’e, work’ten main’e).
rebase kullanıldığında örnek Git Geçmişi:

rebase kullanıldığında örnek Git Geçmişi
Çok daha az merge commit’i ve karmaşık görsel branch birleşme döngüsü olmayan çok daha temiz bir Git geçmişi.
rebase’in dezavantajları veya tuzakları var mı?
Evet:
rebasecommit’leri taşıdığı (teknik olarak yeniden uyguladığı) için, taşınan tüm commit’lerin tarih bilgisi rebase zamanı olur ve git geçmişi ilk commit zamanını kaybeder. Yani bir commit’in tam tarihi herhangi bir nedenle önemliyse,mergedaha iyi bir seçenektir. Ama genellikle temiz bir git geçmişi kesin commit tarihlerinden çok daha kullanışlıdır.Rebase yapılan branch’te aynı satırı değiştiren birden fazla commit varsa ve o satır temel branch’te de değiştirilmişse, aynı satır için merge conflict’ini birden fazla kez çözmen gerekebilir. Merge yaparken bunu hiç yapmana gerek kalmaz. Yani ortalama olarak çözülecek daha fazla merge conflict’i olur.
rebase kullanırken merge conflict’lerini azaltma ipuçları:
Sık sık rebase yap. Genellikle günde en az bir kez yapmayı öneriyorum.
Aynı satırdaki değişiklikleri mümkün olduğunca tek bir commit’te birleştirmeye (squash) çalış.
Umarım bu SSS bazı takımlara faydalı olur.

