git dersleri

Git Revert: Commitleri Geri Almak

Merhabalar, bir projede çalışırken bazen yaptığımız değişiklikleri geri almak zorunda kalabiliriz. Bu dersimizde git revert ile bu işlemin kolay ve pratik bir şekilde nasıl yapıldığını işleyeceğiz.

Neden geri alalım?

Yaptığımız bir commit’i geri almanın birçok sebebi olabilir. Bunların en başında yayına veya müşteriye teslim edilen bir kodun hatalı olduğunu görüp onu geri almak zorunda kalabilirsiniz. Belki yaptığınız değişiklik düzgün çalışsa da müşterinin sevmediği bir özellik olabilir. Diğer bir sebep parola, API anahtarı gibi önemli bir veriyi yanlışlıkla kod deposuna göndermiş olabilirsiniz. Bu durum daha can sıkıcı olabilir. Burda yapılacak şey genelde parola veya API anahtarı değiştirmektir. Genellikle yerelde çalıştığımız bir işi eğer uzak bir sunucuya göndermediysek onu bir şekilde ortadan kaldırmamız kolay. Fakat commit’leri göndermek bir git push komutu kadar kolaydır. Ya da bir git servisi kullanıyorsanız bir butona basmanız yeterli olacaktır.

Git Tarihçesi

Önceki derslerimizden bahsettiğimiz gibi bir depoda yaptığımız değişikliklerin tarihçesi önemlidir. Geliştiricilerin genellikle yaptığı hata ilgili commit’i tamamen ortadan kaldırmaya çalışmaktır. Bu durumda git history diye tabir ettiğimiz tarihçe değişmiş olacaktır. Git ise bu tür durumlara karşı bir çeşit koruma görevi görmektedir. Eğer ortak çalışılan bir branch’e istemediğiniz veya geri almak istediğiniz bir commit göndermişseniz, onu tamamen atmak yerine geri almak daha iyi bir çözüm olacaktır. Git de bir commit’i tamamen yok etmek mümkün elbette ama bunu yaparsanız git pushkomutu varsayılan olarak hata verip yaptığınız değişiklikleri göndermenizi engeller.

Bunu deneyebiliriz. master‘dan yeni bir branch çıkalım ve bunu git push ile gönderelim. Daha sonra bu branch’i yerelimizde silip git checkout geriye gidip aynı isimli bir branch oluşturup bunu da uzak bir depoya göndermeye çalışalım:

Son halini göndermeye çalıştığımızda aşağıdaki hatayı aldık.

! [rejected]        push-test -> push-test (non-fast-forward)                                                        
error: failed to push some refs to '[email protected]:mobilhanem/half-life-2.git'                                        
hint: Updates were rejected because the tip of your current branch is behind                                          
hint: its remote counterpart. Integrate the remote changes (e.g.                                                      
hint: 'git pull ...') before pushing again.                                                                           
hint: See the 'Note about fast-forwards' in 'git push --help' for details.

Hata mesajında bize belirtilen ipucu git pull yaparsanız. Silmek istediğiniz commit’in geri döndüğünü farkedersiniz. Bu arada yukardaki komutların sonunda push-test branch’ini hem yerelden hem uzak sunucudan sildiğimizi de belirtelim.

Bunun çözümü elbette mevcut fakat bu konuyu biraz daha derinlemesine ilerleyen derslerimizde inceleyeceğiz.

Çözüm

Tarihçeyi değiştirmeden yapılması gereken tek şey var. O da adımları geri izlemek. Yani yaptığımız değişikliklerin tam tersini yapan yeni bir commit yapmak. Git’in revert özelliğini bilmeyen biri muhtemelen kullandığı IDE veya text editörü neyse onu kullanıp değişiklikleri geri alıp yeni bir commit yapardı. Fakat bu yine riskli bir durum olabilir. Yaptğımız değişiklik istenmeyen sorunlara sebep olabilir. Bir de yaptığımız değişiklik bir kaç commit gerideyse bunu yapmak daha zor olabilir.

Git’in adımları geri izlemek için kullanabileceğimiz bir komutu var.

Git Revert

Şu an master‘da bulunan son commit’i yani ‘Add chapter 6’ mesajlı commit’i geri alalım. Bunu yapmak için git revert komutunu kullanacağız.

Son commit’i geri almak istediğim için git revert‘i HEAD parametresi ile kullandım. Siz istediğiniz bir commit’in id’sini parametre olarak girebilirsiniz. Revert işlemi yeni bir commit yarattığından ve revert işleminin aslında yeni bir commit’den farklı olmadığından git push komutu bize direnmedi ve uzak branch’e geri alma işlemini gönderdi. Bu arada ne kadar eski bir commit’i geri almaya çalışırsanız conflict yani çakışma olması bir o kadar da olası bir durumdur. Biz doğrudan son commit’i geri aldığımız için çakışma yaşama olasığımız sıfırdı.

Tarihçeye bakarsak yeni bir commit yaptığımızı ve bunu geri aldığımızı da görmüş olacağız. Geri alma işlemi de aslında bir değişiklik olduğu için bunun tarihçede yer alması oldukça iyi bir durum. Eğer parola gibi bir bilgiyi göndermiş olsaydık malesef o bilgi tarihçede yer almaya devam edecekti. Özellikle herkese açık bir depoda böyle bir hata yaparsanız mutlaka o parolayı geçersiz hale getirin.

Geri almayı geri almak

Peki geri aldığımız değişikliği tekrar aktif etmek istersek ne yapmalıyız? Editörü açıp aynı şeyleri tekrar yapıp yeni bir commit mi yapalım? Tabiki de hayır. git revert komutunun yeni bir commit yarattığını söylemiştik. O zaman bu commit’i de geri alabiliriz. Bu sefer HEAD yerine commit’in id’sini kullanacağım fakat burda da HEAD kullanabilirsiniz.

Gördüğümüz gibi chapter6 geri geldi. Şimdi bir son commit’i kullanarak bir daha geri alalım. Canınız sıkıldıysa ve zamanınız varsa bu işlemi dilediğiniz kadar tekrarlayabilirsiniz 🙂

Birden fazla commit’i geri almak

git revert ile birden fazla commit’i de tek seferde geri alabiliriz. Fakat ondan önce revert-multiple-commits adında bir branch oluşturup, 2 yeni commit yapalım.

  1. Commit
Chapter 7
=============

Freeman is informed that Eli Vance has been taken to Nova Prospekt and sets out on a journey along Highway 17 to rescue him. The player encounters Combine Soldiers for the first time as well as a new type of Xen alien, the Antlions. Colonel Odessa Cubbage is also met in this level, giving Gordon the RPG. Gordon deactivates Force Fields in order to progress across a bridge.
  1. Commit
Chapter 8
=============

Continuing on to Nova Prospekt, Gordon exits a Zombie-infested tunnel, fends off a Combine raid on Lighthouse Point, and passes through the last part of the coast without the Scout Car. He encounters the first Antlion Guard of the game and is then trained in usage of the Antlion Guard's pheropods by a Vortigaunt working with the Resistance. He then continues to the final part of the coast, where he battles many Nova Prospekt guards on his way into the prison. In this chapter, Antlions become the player's allies, since Gordon has the Bugbait pheropod.

Şimdi aynı branch’te yaptığımız iki commit’i birden revert edelim. Bunun için aşağıdaki formatı kullanacağız:

git revert -n <ilk-commit>..<son-commit>

Bu komut verdiğimiz iki commit arasındaki commitleri revert eder. Diğerinden bir farkı daha otomatik olarak bir commit üretmez. Bunu yaptıktan sonra commit işlemini yine biz yapmak zorundayız. Şimdi bu branch’te deneyelim.

Birleştirmeyi Geri Almak

Merge işleminin tamamını da geri alabiliriz. Fakat bundan önce mastera geri dönüp yeni bir branch oluşturup yine yukardaki ‘Chapter 7’ ve ‘Chapter 8’ commit’lerini yapalım.

Şimdi master a geri dönüp merge işlemini yapalım. Burdaki önemli nokta –no-ff parametresini unutmamak. Yoksa git merge commit’i olmadan merge işlemini yapar. Bunu yine ilerleyen derslerimizde anlatacağız.

Şimdi master’a baktığımızda bir merge commit’i ve bunun içerisinde ‘Chapter 7’ ve ‘Chapter 8’ commitleri var. Şimdi master’a yaptığımız bu merge işlemini geri alalım. Bunun için aşağıdaki komutu kullanabiliriz.

git revert -m <mainline> <merge-commit-id>

Burdaki revert işlemini yaparken hangi seviyeyi revert etmek istediğimizi tanımlıyoruz. Biz master‘a tek seviyeli bir merge işlemi yaptığımız için 1 değerini vereceğiz. Bu konu karışık ve oldukça kafa karıştıran bir konu. Şimdilik çok fazla takılmanıza gerek yok ve sonraki derslerimizde bu konuya değineceğiz. Şimdi revert işlemini yapalım.

‘Chapter 7’ ve ‘Chapter 8’i geri almış olduk.

Not: Bu arada merge içindeki commit’leri de tek tek revert edebilirsiniz. Eğer tek bir commit varsa merge’i geri almakla uğraşmanıza gerek yok.

Chapter 6, 7 ve 8 Geri Gelsin

Şimdi sırayla yaptığımız işleri geri getirelim. Bunun için öncelikle 6 daha sonra 7 ve 8’i beraber getireceğiz.

vee conflict. ‘Chapter 7’ ve ‘Chapter 6’, ‘Chapter 5’ten hemen sonra eklendiği için çakışma yaşadık. İlgili düzenlemeyi yapıp git revert --continue komutunu kullanabiliriz.

Bir dersimizin de sonuna gelmiş olduk. Bu derste git revert komutu ile yaptığımız commit’leri geri almayı detaylı bir şekilde öğrenmiş olduk. Commit’leri geri almadan ortadan kaldırmak için sonraki derslerimizi bekleyiniz.

Konu hakkında görüş ve sorularınızı yorum kısmından veya Soru & Cevap sitemizden sorabilirsiniz.

Bir sonraki derste görüşmek üzere…

Git derslerinin tamamı için tıklayınız.

20

Ömer Özkan

Genelde Java teknolojileri ile geliştirme yapar. Özgür ve açık kaynak yazılımlara meraklıdır. Boş zamanlarında gönüllü eğitimler verir. Onun için Clean Code, Test Driven Development gibi konular oldukça önemlidir.

1 Yorum

  • Bu revert ile istediğimi tam yapamıyorum. Mesela Chapter 4 commit ettim sonra aynı dosyaya Chapter 5 ettim. Şimdi ben Chapter 5 iptal olmadan sadece chapter 4 iptal etmek istiyorum. Bunu yapmak istediğimde de aşağıdaki ifade oluşuyor. Bu örnekte görüldüğü gibi tamamen karmaşa oluşuyor. Ben Chapter 4 iptal etmek istedim ama Chapter 4 nerede bitiyor belli değil. Bu tip sorunu nasıl çözebiliriz?
    Chapter1
    Chapter2
    <<<<<<>>>>>> parent of c9a6a65 (ch4)

Haftalık Bülten

Mobilhanem'de yayınlanan dersleri haftalık mail almak ister misiniz?