GIT Nedir ?

Herkese selamlar ✋, ilk yazımla Medium’a adım atmış bulunmaktayım. Bu ilk yazım ve tabii ki de birçok kez sorun yaşadığım, her karşılaştığım sorunda araştırıp yeni şeyler öğrenip çalışma mantığını az çok kavradığıma inandığım Git üzerine olmalıydı 🚀 Özlemle hatırladığım öğrencilik günlerimde “bir commit bir push nedir ki ne kadar zor olabilir” dediğim çok oldu tabii. İşin içine girdikçe konunun önemini çok daha iyi kavradım diyebilirim.

Googleladığımda hemen hemen her yazının ilk cümlesinin “git bir versiyon kontrol sistemidir” olduğunu gördüm. Peki versiyon kontrol sistemi nedir? Okuduğum yazılardan anladığım basitçe bir dosyanız var ve bu dosyanın oluşturulma tarihinden başlayarak istediğiniz tüm durumlarını takip edebildiğiniz bir yapı tasarlıyorsunuz. Bu yapının sorun çıkarıp çıkarmaması tamamen bizim elimizde. Ne kadar iyi tasarlarsak ne kadar çok commit atıp geri dönebileceğimiz noktalar oluşturursak, yönetimi kolay bir yapı tasarlamış oluruz. Kısaca yazılım projemizin tüm anlarını kayıt altına alıyormuşuz gibi düşünebiliriz.

Kurulum

Öncelikle https://git-scm.com/downloads bu linke giderek işletim sistemimize uygun bir versiyon indirmemiz ve basit adımlarla kurulum yapmamız gerekiyor.

git — version komutuyla git versiyonumuzu öğrenebiliriz.

Kurulumu tamamladıktan sonra proje üzerinde yaptığımız tüm değişikliklerin tutulabilmesi için name ve email bilgilerimizin konfigürasyonunu yapmamız gerekiyor.

Burada yaptığımız konfigürasyon ayarı kullanıcıya özeldir.

Repository

Localimizdeki bir projeyi versiyonlamak istediğimizde proje klasörü içerisinde git init komutunu çalıştırmamız yeterli olacaktır. Böylelikle proje içerisinde .git klasörü oluşacaktır ve bu bizim local repository’imiz olacaktır.

Remote repository ise bir sunucu da yer alan projemizin .git klasörüdür. Örneğin; https://github.com/googlecodelabs/android-navigation.git adresindeki repository’ı üzerinde geliştirme yapmak istediğimizde git clone url komutuyla üzerinde çalışmalara başlayabiliriz. Localimizde bu projenin bir kopyası oluşacağı için proje üzerinde yapmış olduğumuz değişiklikler remote’daki repository’i etkilemeyecektir.

Projelerimizde versiyonlamak istemediğimiz dosyalar ve klasörler varsa projeye .gitignore uzantılı dosyayı eklememiz gerekiyor.

https://github.com/github/gitignore bu adresten .gitignore uzantılı dosyaların hazır templatelerini bulabilirsiniz veya ihtiyacanıza göre bu dosyaları kendinizde düzenleyebilirsiniz.

Projeye başladık ve bazı dosyaları .gitignore dosyasına eklemediğimizi farkettik. Bu gibi durumlarda .gitignore dosyasını düzenleyebiliriz. Bir başka seçenek olarak

git rm — cached “dosya uzantısı” komutunu da kullanabiliriz.

Staging Area

Evet local ve remote repository mantığından bahsettik. Şimdi de git’in en temel kavramlarından biri olan staging area’ya geldi sıra. Local repository üzerinde değişiklik yaptık ve bunu sunucuya göndermek istiyoruz. Git’teki bazı komutlar yardımıyla öncelikle bu değişiklikleri staging area’ya almamız gerekir. Peki staging area neden var ve neden buraya almalıyız şöyle düşünebilirsiniz internet’in olmadığı bir yerde proje geliştiriyor olabilirdik bu durumda internet bağlantısı olmadan yaptığımız tüm değişiklikleri gruplayarak staging area’ya alabiliriz. Yani staging area bize internet bağlantısı olmadan bile geliştirme yapmamızı sağlıyor. Tabii bence bunu gruplayarak ve işin tanımına uygun mesajlar yazarak yapmamız en güzeli olacaktır. Daha önce belirttiğim gibi ne kadar çok geriye dönük noktalar oluşturabilirsek projeyi versiyonlamamız daha mantıklı hale gelecektir.

Öncelikle commitlemek istediğim değişiklikleri belirleyip git add “dosya uzantısı” komutu ile staging area’ya alıyorum. Tüm değişiklikleri staging area’ya almak istersem kısaca git add * komutunu kullanabilirim. Staging area’ya alma işlemi bittikten sonra değişikliklerimi git commit -m “commit mesajı” komutu ile commitleyebilirim.

git add komutuyla staging area’ya aldığım bir değişikliği

git reset HEAD “dosya uzantısı”

komutu ile staging area’dan çıkartabilirim. Yaptığım işlemleri geri almak için bunun dışında birçok git komutu bulunmaktadır. Genel olarak kullandıklarımı kısaca açıklamaya çalışacağım.

git rm -f “dosya uzantısı”

Dosyayı projeden tamamen silmiş olacağız.

git commit -amend -m “commit mesajı”

Son commit mesajını değiştirebiliriz.

git checkout -“dosya uzantısı”

Dosya uzantısının staging area’yada olmayan değişikliklerini silip ve dosyayı commit edilen son noktaya geri döndürebiliriz.

git reset -hard

Projede yapılan tüm değişiklikleri silip ve son commit edilen noktaya geri getirebiliriz.

git reset [hash değerinin ilk 7 karakteri]

Commitlediğimiz değişiklikleri geri almamızı sağlar. Bu işlemi yeni bir commit oluşturmadan yapar.

git revert [hash değerinin ilk 7 karakteri]

Commitlediğimiz bir değişikliği geri alırken projemizin tarihçesinden atmış olduğumuz commit’i silmez ve değiştirme işlemini yeni bir commit atarak gerçekleştirir.


git status

Proje üzerinde değişiklikler yaptık ve tüm değişiklikleri liste halinde görmek istiyoruz bu durumda git status komutuna kullanabiliriz. Bu komut belli gruplar halinde tüm değişiklikleri dönecektir.

Untracked files: Git tarafından takip edilmeyen tüm dosyaları burada görebiliriz.
Changes not staged for commit: Bu listedeki dosyalarda değişiklik yapmışız fakat henüz staging area’ya bu değişiklikleri bildirmemişiz.
Changes to be committed: Staging area’da olan commitlenmeyi bekleyen tüm dosyaları burada görebiliriz.

Branch

Git ağaç mantığı ile çalışmaktadır. Bir projeyi versiyonlamak istediğimizde git otomatik olarak master branch’ini oluşturur ve biz bu branch üzerinde çalışmaya başlamış oluruz. Peki neden branchlere gerek duyalım? Bunun bence birden fazla sebebi var. Okulda yaptığımız ufak projelerden tutun, sektördeki birçok şirkette bir proje birden fazla geliştirici tarafından geliştirilir. Yetkili olduğunuz bir projede değişiklik yapmak istediğinizde direk master branch’i üzerinde değişiklik yaptığınızı ve tüm ekibinde bu branch üzerinde çalıştığını düşünün olay çok karmaşık ve yönetilemez bir hal alacaktır. Bir diğer neden ise iki kişi farklı konular üzerinde çalışıyorlarsa farklı branchlerde çalıştıkları için birbirlerini etkilemeyecektir. Yaptığımız tüm değişiklikler sadece bulunduğumuz branch’i etkileyeceği için başka branch açarak farklı bir konuda da geliştirme yapabiliriz ve bunlar birbirlerini etkilemeyeceği için kodu // gibi yorum satırına almaktan veya silmek zorunda kalmaktan kurtulmuş olacağız.

git branch branchadı

Bulunduğumuz branch’den yeni bir branch çıkabiliriz.

git branch

Projedeki local branchleri görebiliriz.

git branch -v

Projedeki local branchleri son commit bilgisi ile görebiliriz.

git branch -va

Local’deki ve remote’daki branchleri liste halinde son commit bilgileri ile görebiliriz.

git checkout branchadı komutuyla branch’ler arasında geçiş yapabiliriz.


Oluşturduğumuz branch’lerle işimiz bittiğinde veya başka bir nedenden dolayı bu branch’leri silmek isteyebiliriz. Local’deki bir branch’i silmek istersek

git branch -d branchadı komutunu kullanabiliriz.

Silmek istediğimiz branch remote repository de ise

git branch -dr branchadı
git push origin :branchadı

komutları yardımıyla bu branch’i remote repository’den silmiş olacağız.


git stash

Bir branch üzerinde çalışırken tam olarak bitmeyen tüm değişiklikleri commitlemeden kayıt altına alıp branch’i ilk durumuna döndürmek isteyebiliriz. Bu durumda tam olarak git stash komutunu kullanmamız gerekir. Bu komut commitlenmemiş tüm değişikliklerimizi kayıt altına alıp branch’i ilk haline çevirir. git stash list komutu ile de geçici olarak kayıt altına alınan değişikliklerin listesini görebiliriz.

git stash pop

Stash list’de olan en üstteki değişikliği geri yükler ve değişiklikleri silebiliriz.

git stash apply stash@{listId}

Stash list’deki değişikliği silmeden geri yükleyebiliriz.

git stash drop

Değişikliği geri yüklemeden stash list’den siler. Bu birazcık tehlikeli bir komut gibi duruyor 👹


git commit sonrası

Bulunduğumuz branch’de commit işlemlerini tamamladık ve artık branch üzerinde yaptığımız tüm değişiklikleri remote repository’de görmek istiyoruz.

Bu branch remote repository’de ilk kez oluşturulacaksa, git push origin branchadı komutunu kullanarak branch’i remote repository’e pushlayabiliriz. Ama bu branch remote repository’de varsa ve başka geliştiricilerde bu branch üzerinde çalışıyorlarsa

git fetch

komutunu kullanarak başka biri tarafından değişiklik yapılıp yapılmadığına bakmamız gerekecektir. Projede aynı branch üzerinde çalıştığımız takım arkadaşlarımız var ise geliştirme yapmaya başlamadan önce bu komut yardımıyla remote branch’deki tüm değişiklikleri local branch’imize almamız gerekir. Bu iki branch arasında farklılıklar bulunuyor ise branch’ler arasında çakışmalar meydana gelebilir.

git diff komutu ile iki versiyon arasındaki farkları inceleyebilirim.

Farkları inceleyerek remote branch’deki tüm değişiklikleri local branch’ime alarak local branch’imi çalışır en güncel hale getirmeliyim. Bence bunun nedeni ise local branch’imi push’ladığımda hem kendi geliştirmelerim hemde remote’daki tüm geliştirmeleri içeriyor olması gerektiğidir. Tüm çakışmaları giderirsek artık local’imizdeki branch’i güncel versiyon olarak push’layabiliriz.

git rebase ve git merge

Master branch’inin otomatik oluşan ilk branch olduğunu daha öncede belirtmiştim. Master branch’inden geliştirme yapmak için development branch’ini çıktığımda ve development branch’deki tüm geliştirmeleri tamamladığımda bu iki branch’i birleştirmem gerekiyor ki development branch’inde yaptığım tüm değişiklikleri master branch’imde görebileyim. Bu nedenle development branch’imdeki tüm değişiklikleri master branch’ime aktarmam gerekecektir. Bu işlemi gerçekleştirmeden önce dikkat etmemiz gereken tek bir nokta vardır. Master branch’imden development branch’imi çıktıktan sonra bu branch’de herhangi bir değişiklik olup olmadığıdır.

Master branch’imde herhangi bir değişiklik olmadıysa yani bu branch’in son commit’i ve development branch ile ortak commit’i aynı ise git git rebase ile bu branch’i master ile birleştirebilirim.

git checkout master komutu ile master branch’ini head yapıyoruz. Daha sonrada git rebase develop komutu ile master branch’ine develop branch’inin tüm tarihçesini aktarmış oluyoruz. Develop branch’indeki tüm değişiklikler artık master branch’imizdede bulunuyor.

Master branch’inin ortak commit’i ve son commit’i farklı ise yani ben master branch’inden development branch’ini çıktıktan sonra bu branch üzerinde değişiklik olduysa git merge komutu ile development branch’ini master’ın son hali ile birleştirebilirim.

Bunun için ise rebase’de olduğu gibi öncelikle git checkout master komutu ile değişikliğin aktarılacağı branch’i head yapmam gerekecek. Daha sonra da git merge branchadı komutuyla merge işlemini gerçekleştirmiş olacağım.

Aslında bakarsanız merge ve rebase çok daha detaylı öğrenilmesi gereken komutlar ben her ikisinden de çok kısaca bahsetmek istedim. Burada tercih tamamen size kalmış her iki durumdada sadece merge kullanabiliriz. Merge ve rebase kullanımını daha detaylı anlatan birkaç kaynak ekliyor olacağım.


Evet neredeyse git ile ilgili tüm komutları açıklamaya çalıştım. Konuyla ilgili önerileriniz ve sorularınız varsa yorumlarınızı bekliyorum.

Okuduğunuz için teşekkür ederim 👍

Görüşmek üzere…