Git -Fast Forward, Merge Conflict, Stash

Kübra Özden
11 min readNov 13, 2023

--

Fast Forward

Git’te fast forward işlemi, iki branch’in tarihçelerinin tek bir çizgi halinde birleştirilmesi işlemidir. Bu işlem, iki branch’in son commit’leri aynı olduğunda gerçekleşir.

Fast forward işleminin yapılmasının başlıca iki nedeni vardır:

  • Değişikliklerin ana daldan izole edilmesini sağlamak: Bir feature branch üzerinde çalışırken, değişikliklerin ana dalda bulunan mevcut kodla çakışmasını önlemek için fast forward işlemi kullanılabilir. Bu, değişikliklerin test edilmesini ve geri alınmasını kolaylaştırır.
  • Projenin geçmişini daha anlaşılır tutmak: Fast forward işlemi, projenin geçmişini daha anlaşılır tutmaya yardımcı olur. Yeni bir commit oluşturmak yerine, mevcut bir commit’in üzerine yeni değişiklikler eklenir. Bu, geçmişteki değişiklikleri takip etmeyi kolaylaştırır.

Fast forward işlemi, aşağıdaki komutla gerçekleştirilir:

git merge <branch_adı>

Örneğin, “feature” branch’ini ana dal (master) ile birleştirmek için aşağıdaki komutu kullanabilirsiniz:

git merge feature

Bu komut, “feature” branch’indeki değişiklikleri ana dal’a uygular. Eğer “feature” branch’inin son commit’i ana dal’ın son commit’iyle aynıysa, fast forward işlemi yapılır ve ana dal’ın tarihçesi “feature” branch’inin son commit’i ile güncellenir.

Fast forward işlemi, her zaman mümkün olmayabilir. Örneğin, iki branch’in son commit’leri farklıysa, merge işlemi sırasında bir merge commit oluşturulur. Merge commit, iki branch arasındaki değişiklikleri içeren yeni bir commit’tir.

FAST FORWARD İŞLEMİ NASIL YAPILIR ?

  • Merge konusunda işlemlerimiz yaparken feat de yeni bir dosya açtık onun içine yazdık master da öyle bişey yapmadık olanın üzerine yazdık. Peki ya feat de yeni bir dosya açmasaydık hatta güncel dosyanın içeriklerini silseydik ama master da silmeseydik ve yeni şeyler ekleseydik yani ortalık biraz karışsaydı ne olurdu ?
  • Bunları birleştirirken conflict ( çakışma ) olacaktı. Birbiriyle tutarlı değil yani birinde bi satırı siliyoruz diğerinde silmiyoruz vs.
  • Çakışma olmaması için Yeni bir branch açıp orada commit atarız master da hiçbir şey yapmayız. Böylece hiç çakışma olmayacağı için rahatlıkla merge edebiliriz. Buna FAST FORWARDİNG (ileri sarmak ) diyoruz.
  • Yani aslınca bu işlemleri master üzerinde de götürebiliriz ama yeni bir branch açmışız orada bu değişiklikleri yapıyoruz çalışırsa merge eder yani ekler geçeriz çalışmazsa sileriz.
  • Arkakapak adında bir branch açtık içerisine kapakyazisi.txt dosyası oluşturduk ve 2 satır yazıp 2 commit attık . Bunların hepsi Arkakapak branchinde yapıldı bu sırada master da hiçbir şey yapmadık.
  • git switch master diyip master branch e gidip git log dediğimizde master da en son yapılan commitleri görüyoruz. Master branch e geçtiğimiz için sublime text de kapakyazisi.txt gitmiş oluyor çünkü o Arkakapak branch de kaldı.
  • Master branch de git merge Arkakapak diyerek merge işlemini gerçekleştiriyoruz.
  • göründüğü gibi Fast-forward olarak orada da görünüyor.
  • git log yaptığımızda HEAD → master, arkakapak diyor. Yani bizden yeni bir birleştirme commiti oluşturmamızı bile istemedi. Çünkü öyle bir durum yok ki yani aslında burada yeni bir commit bile oluşturmuyor, yeni branch deki özellikleri master a alıyor.
  • Daha sade görselleştirmesine bakarsak aslında yukarıdaki branch deki commitleri master a getiriyor. Ve şuanda ikisi aynı commiti share ediyor. Ama artık feature buraya merge edilmiş olduğu için
  • head → master şeklinde görünüyor.

MERGE CONFLİCT NEDİR ?

Merge conflict, Git’te iki branch’in birleştirilmesi sırasında ortaya çıkan bir durumdur. Bu durum, aynı dosyanın aynı satırı her iki branch’te de değiştirildiğinde ortaya çıkar. Git, bu durumda otomatik olarak merge işlemini gerçekleştiremez ve kullanıcıdan çakışmayı çözmesini ister.

Merge conflict çözmek için, kullanıcı her iki branch’teki değişiklikleri inceleyip hangi değişikliğin ana dala uygulanması gerektiğine karar vermelidir. Kullanıcı, değişiklikleri manuel olarak düzenleyerek veya her iki değişikliği içeren yeni bir değişiklik yaparak çakışmayı çözebilir.

Merge conflict, aşağıdaki durumlarda ortaya çıkabilir:

  • İki kişi aynı dosyanın aynı satırını aynı anda değiştirir.
  • Bir kişi bir dosyada değişiklik yapar ve ardından başka bir kişi aynı dosyadaki farklı bir satırda değişiklik yapar.
  • İki kişi aynı dosyada aynı satırı farklı şekillerde değiştirir.
  • Yeni bir klasör oluşturup örneklerimize buradan devam edelim. JavaKitabi klasörü oluşturduk içine girip git status ile .git var mı diye kontrol edip (tabi ki yok yeni oluşturduk ama alışkanlık olsun) git init ile versiyon kontrol sistemini başlatmış olduk. İçerisine ilkbolum.txt dosyası oluşturduk
  • ilkbolum.txt noktasına satırlar eklendikten sonra bash de bu değişiklikleri commit ediyoruz.
  • bir arkakapak branch açtık ve git switch arkakapak branch e gittik.
  • Burada yapılan değişiklikleri commit attıktan sonra master branche gidiyoruz. Ve ilkbolum.txt dosyasını sildik onun yerine yeni bir dosya olan touch bolum1.txt dosyasını açıyoruz.
  • bolum1.txt dosyası içerisinde yeni bir satır ekliyoruz ve “ilk bolum tekrar yazıldı “ olarak commit ediyoruz.

İŞTE ÇAKIŞMANIN OLDUĞU KISIM yukarıdaki bash ekranında otomatik olarak ben bunları birleştiremiyorum diyor yani diyor ki “ ilk bolum.txt yi silmişsin ama arkakapak da bunu modifiye etmişsin yani arkakapak da ilkbolum.txt nin içerisinde değişiklik yapmışsın sonra da gidip bunu silmişsin “ yani ne yapılmaya çalışıldığını anlamıyor, çakışma oluyor. conflict leri çöz ondan sonra gel diyor 🙂

  • Bunu çözebilmek için sublimetext e baktığımızda bize bir tane dosya oluşturmuş ve üzerinde bir işaret var. Burada bir karar vereceğiz “arka kapak güzel oldu” mu tutacağız yoksa bolum1.txt yi mi tutacağız.
  • ilkbolum.txt silip “arka kapak güzel oldu” ifadesini kesip bolum1.txt ye yapıştırabilirim.
  • Ya da bolum1.txt yi de silebiliriz.
  • Biz ikisini de save edelim
  • İkisini de save ettikten sonra git merge arkakapak dedik. Merging is not possible because you have unmerged files : Birleştirilmiş dosyalarınız olduğundan birleştirme mümkün değil. Yani tamam kaydettin ama bunu doğru düzgün yapabilmek için dosyalarını ekle ondan sonra da commit yap diyor.
  • git status dediğimizde ilkbolum.txt geri geldi diyor. Eğer ilkbolum.txt yi kullanacaksan save etmekle olmuyor bunu commit yap diyor.
  • git add . ve git commit -m “merge conflict çözüldü” komutları ile commit ettik ve ardından git merge arkakapak komutu ile merge işlemini gerçekleştirdik. already up to date diyor yani işlem zaten gerçekleşmiş.
  • git log dediğimizde ilk bolum tekrar yazıldığında ilk bölümün içerisindeki şeyi silmiştik. merge conflict çözüldü commitinde burada conflict çıkartan dosyayı tekrar koyduk commitledik. O yüzden artık içeri alabildi bunu
  • ilk bolum tekrar yazıldığı için ikisini aynı commite point etmiyor. “ head → master “diyor ama “head → master, arkakapak” demiyor.
  • Ama şuanda master içerisinde arkakapak da var. O yüzden zaten olduğu için merge ettim diyor. Arkakapak branch inde olan bitin commit ler master branch de de var.
  • Başka bir conflict şekli olabilir. Mesela master branch de yeni bir dosya açtık java dosyası ornek.java diye bunun içerisine 1 satır kod ekledik. daha sonra git branch feat komutu ile yeni bir branch açıp bu branch içerisine girdik
  • ve sublimetext de bu ornek.java dosyasını değiştirip save ettik. bash de feat branch de indexleyip commitledik .
  • Daha sonra master branche gidip git status çalıştırdığımızda bir sıkıntı görünmez. ornek.java dosyası içerisindeki satırı silip save ettik git add . ve git commit -m “email silindi” commiti attık. git merge feat dediğimizde bize CONFLİCT hatası verir.
  • burada bize bir mesaj gösteriyor. ( Bir önceki confllict de olay daha kolaydı bi dosya silinmiiş geri getireyim mi getirmeyim mi diye soruyordu ) Burada ise aynı dosya içerisinde olduğu için conflict bize bu mesajı gösteriyor.

→ Bize diyor ki ; sen güncel olan yerinde (masterda) silmişsin diyor. Fakat feat içerisinde bunu yazmışsın, kısaca karar ver diyor ornek.java içerisinde ne olmasını istiyorsun, feat mi olsun yoksa olmasın mı ? karar bize bağlı istersek ornek.java dosyası içerisini komple silebiliriz bunu yaparsak da master daki halini tut demek aslında ya da

Bu şekilde bırakabiliriz bu da feat şeklini tut demek bütün bunları silip başka bişey de yazabiliriz

  • Buradaki gibi bambaşka bir şey de yazabiliriz yani burada ne yapıp yapmayacağımız bize kalmış conflict çöz ama nasıl çözersen çöz 🙂

STASH

  • Biz daha önce branchleri birleştirdik ve hepsinde yeni bir commit oluşturuldu. Mesela feat branch in de merge yapmadan önce işimizi bitirdik commit yaptık sonra birleştirdik yani zaten bütün değişikliklerimizi commitlemiştik ondan sonra birleştirdik. PEKİ YA COMMİT YAPMAZSA?
  • Biz içimize sinemeyen, yarım kalmış bir şeyi commit etmeyiz. Git add yapabiliriz başka bişey yapabiliriz ama genelde bitirdiğimiz bişeyi commit ederiz. Her şeyin çalıştığı içimize sinen noktada commit ederiz genelde
  • Mesela feat içerisindeyiz çalışıyoruz daha commit etmedik git add vs yaptık ama git commit yapmadık ve oldu ki mastera geri dönemem gerekti, acil bişey çıktı git switch master yapmam gerekti ?
  • → Gidersem buradaki değişiklikler ne olacak commit etmedik çünkü ?
  • → Git hata verecek mi ?
  • ekstrabolumler diye yeni bir branch oluşturduk ve bu branch içerisine ekstrabolum.txt dosyasını açtık dosya içerisine satırlar ekledik falan git add . dedik ama commitlemedik ve ekstrabolumler branchinde çalışırken bir nedenden dolayı master branche dönmemiz gerekti ve git switch master dedik
  • master branche döndüğümüzde ekstrabolum.txt dosyamızın normalde burada görünmemesini bekleriz ama yanında added işareti ile birlikte bizimle gelmiş.
  • İşte bu olabilir. Çünkü daha önceden master branche de böyle bir dosya olmadı hiç çakışan bir şey yok işte böyle bir olayda branch değiştirdiğimizde dosyayı de getirir bize, İstersek bunu master içerisinde de git add . veya **** git commit yapabiliriz.

DİKKAT ! Bu hiç master da olmayan çakışma olmayan bir dosya olduğu için özellikle

  • ekstrabolumler branche geri dönüp commit ettikten sonra git switch master dediğimizde artık ektrabolum.txt dosyası burada görünmeyecektir.
  • Commit ettiğimiz için tekrar mastera taşımasına gerek yok çünkü artık o ektrabolumler branchinde kaldı.
  • git switch ekstrabolumler diyerek branhe geçtik ve ardından sublimetext de ilkbolum.txt dosyasının içerisinde bazı değişiklikler yaptık. Fakat bu değişiklikler sadece bu branchi ilgilendirmeli yani şuan bu değişikliklerin master da değişmemesi gerek ve zaten öyle çalışıyor.
  • Git status dediğimizde bu değşikliğin kaydedilmediğini görüyoruz
  • Fakat bizim mastera gitmemiz gerekti ve git switch master dediğimizde bize ya hata verecek ( commit yapmadın ve diğer tarafa gitmeye çalışıyorsun diye ) ya da bizi yönlendirebilir duruma göre
  • Master branch e döndüğümüzde sublimetexte baktığımızda diğer branch de yaptığımız değişiklikler buraya gelmiş bu YANLIŞ bir şey ! biz bu değişiklikleri master brnach de yapmadık neden böyle oldu ?

BU SORUNU 2 ŞEKİLDE ÇÖZEBİLİRİZ

  1. Master a geldikten sonra git status çalıştırdığımızda ilkbolum.txt nin modifiye edildiğini (halbuki bu branch de yapmamıştık) söylüyor onu git restore diyerek geri alabilirsin diyor. Yani git restore ilkbolum.txt dediğimizde bu dosya son commit de ne durumdaysa ben ona döndürürüm bunu diyor.
  • Ve baktığımızda txt dosyamız eski haline dönmüş. Master kendi haline gelmiş
  • Fakat git switch ekstrabolumler diyerek diğer branch e geçtiğimizde bu sefer bu branch de de ilkbolum.txt nin değişti o da gitti bilgi kayboldu çünkü ben bunu git commit yapmamıştık. Bu gibi durumlarda commit etmeye hazırsak zaten commit ederiz ve herhangi bir bilgi kaybolmaz. Ya bu değişikliklerden vazgeçeriz. Ya hiç save etmeden ctrl + z ile geri alıp save etmek ya da git restore ile eski haline döndürmek ya da STASH yapmak !
  • Stash (saklamak , depolamak) yapmak : Bunları al sakla bir yerde ben görmeyeyim sonra istersem burada uygularım. Yani commit de değil index de de değil working repository de de değil bambaşka ayrı bir yer stash . Git kendi içerisinde bunları saklıyor, istediğim zaman geri alabiliyorum. ( Commit etmeye hazır olmadığımız ama branch değiştirmek zorunda olduğumuz ve yaptığımız değişiklikleri kaybetmek istemediğimiz durumlarda kullanılır 🙂 )

git stash komutu mülakatlarda karşımıza çok çıkar bilmekte fayda var !!

  • extrabolumler branchin de “stash öğreniyoruz” diye yeni bir satır ekledik ve save ettik
  • bash e döndüğümüzden git status dediğimizde ilkbolumun modifiye edildiğini söylüyor bize işte burada biz bu değişikliği stash edeceğiz
  • Bu değişikliği git stash komutu ile depoladığımızda sublimetexte geri döndüğümüzde bu satırın olmadığını görüyoruz. Neden ? Çünkü biz artık bu değişikliği stash ettik yani sakladık,depoladık
  • Master branche gidip işlerimizi hallettikten sonra bu ekstrabolumler brancheine geri döndüğümüzde stashlediğimiz yani sakladığımız değişiklikleri geri nasıl göreceğiz ?
  • Sakladığım yerde veya uygulamak istediğim yerde (çünkü sakladığım yerden ziyade başka bir yerde de görebilirim bunu ) git stash pop diyoruz ve o saklanan satır geri geldi.
  • git stash pop yapınca git stash list komutunu çalıştırdığımızda güncel stashleri verir.
  • birden fazla stash olduğunda istersek bunları tek tek de ekleyebiliriz.
  • Mesela 0. yı eklemek isteyelim git stash apply stash@{0} diyerek ilk stash i ekleyebiliriz yani geri getirebiliriz.
  • Böylece istediğim stashi istediğim yere koyabiliyoruz. Bu kısım biraz detay ama mülakatlarda çok sorulur !!
  • istediğim zaman git stash clear diyerek bütün stashleri silebiliriz.

--

--