December 19, 2011 - Tagged as: git, tr.
Aslında uzun süredir yazdığım kodları github’da tutuyor olsam da git’i son birkaç günde çok daha iyi anladığımı söyleyebilirim. Şu ana kadar yaptığım, sürekli tek bir branch üzerinden çalışarak, diğer bilgisayar geçeceğim zaman veya çalışan bir sonraki sürümü yayınlamak istediğimde push
yapmaktı. Pardus’da geliştirdiğimiz web projesinde bile sadece stajın son gününde, tek bir commit yaptık hehe(neredeyse tüm projeyi tek bir bilgisayarda pair-programming ile geliştirdiğimizden ihtiyaç duymamıştık, değişiklikleri göstermek istediğimde makinamda kurulu apache’yi çalıştırıyordum ve ağ üzerinden test ediyorlardı. tüm dosya sistemim zaten ağ üzerinden paylaşıma açıktı).
Son günlerde büyük oranda deneyse bir 2d platform oyunu üzerinde çalışıyorum ve sık sık eski haline dönmeyi isteyebileceğim ciddi değişiklikler yapıyorum. Git bana bu konuda nasıl yardımcı olabilir diye biraz araştırdım ve şu ana kadar bunları nasıl farketmedim diye kızdım kendime :P .
Kendime not niteliğinde, bazı olmazsa olmaz(benim için) komutları açıklayacağım.
Anladığım kadarıyla bir depoya yazma izninin belirlenmesi biraz da sunucu tarafıyla alakalı. Bizim yapmamız gereken git config --global user.name "isim"
ve git config --global user.email "email"
ile commitlerimizde gözükecek ismi ve maili belirlemek(mail nerede gözüküyor bilmiyorum). Daha sonra eğer github kullanıyorsak ssh anahtarı oluşturup github’a ekliyoruz. Github’da anladığım kadarıyla ssh key’den kullanıcı adına bakıp depoya yazıp yazamayacağımıza karar veriyor. Bu kısımdan emin değilim açıkçası ama aklıma benim neden Clojure github deposuna push yapamadığımı açıklayacak başka bir senaryo gelmedi aehueah.
Git sunucunuzda depoyu bir şekilde oluşturduktan sonra(Github’da web sayfasından tıklayarak falan) git init
ile bilgisayarımızda git deposu oluşturup, buna uzak sunucudaki depoyu git remote add
ile ekliyoruz:
➜ ~ mkdir git-test
➜ ~ cd git-test
➜ git-test git init
Initialized empty Git repository in /home/sinan/git-test/.git/
➜ git-test git:(master) git remote add git-test git@github.com:osa1/git-tests.git
(Bu arada not: zsh kullanıyorum, oh-my-zshda süper eklentiler var, örneğin benim kullandığım git eklentisinde yukarıda da görebileceğiniz gibi bulunduğum branch’ı gösteriyor, commitlenmemiş değişiklikler varsa bir sembolle belli ediyor, git <tab>
yaptığınızda komutları, komutlardan sonra <tab>
yaptığınızda branch adlarını vs. tamamlıyor, mükemmel birşey, bir sürü de tema var ayrıca.)
Depoyu oluşturduktan sonra hiç branch’ımız yok aslında. Ama eğer branch oluşturmadan direkt commit yaparsak master
diye bir branch oluşturuyor. master
adının bir esprisi yok anladığım kadarıyla. Direkt olarak başka isimli bir branch da oluşturulabilir.
git-status
ile commitlenmemiş değişiklik olup olmadığını görebiliyoruz. git-log
tüm branchlara yapılan tüm commitleri bir 53ea667012c2741e7620e093e05132cd08265c06
benzeri kodla gösteriyor. Bu kodun tam olarak ne olduğunu anlamasam da, önceki bir commit’e dönmem gerektiğinde kullanıyorum.
➜ git-test git:(master) git checkout -b "branch2"
Switched to a new branch 'branch2'
➜ git-test git:(branch2) git branch
* branch2
master
checkout
normalde zaten olan bir brancha geçer. Ama eğer “yeni oluştur ve hemen geç” diyorsanız, -b
ile bu şekilde kullanılıyor. git branch
ile de hangi branchda olduğunuzu görürsünüz(benim yaptığım gibi bir zsh eklentisi kullanıyorsanız zaten gözüküyor gerçi).
Branchlar hakkında yazmak istediğim birkaç şey var. Bir tanesi hangi branchda olursanız olun, başka bir brancha merge yapmadan da o brancha push yapabilirsiniz. Şu şekilde:
➜ git-test git:(branch2) git push git-test branch2:master
Bu syntax’a dikkat: branch2’yi master’a pushla diyorum. Gerekli merge’leri kendisi yapıyor, yapamıyorsa push da yapmıyor. Tabii sonra master branch’ına geçip fetch(master) + merge veya direkt merge(branch2’den) yapmak lazım.
Bunu kullanarak şöyle bir çakallık yapabiliyorsunuz, diyelim ki sunucudan bir branchı uçurmak istiyorsunuz:
➜ git-test git:(branch2) git push git-test :branch2
Bu aslında “branch2’ye hiçbir şeyi pushla” gibi bir anlama geliyor(ben uydurdum aehuaeh). branch2’yi sunucudan siliyor yani. Bilgisayarınızdaki depodan da şu şekilde siliyoruz:
➜ git-test git:(master) git branch -D branch2
Ha neden bir branch’ı sunucudan silmek isteyesiniz bilmiyorum. Geri dönmek isteyebilirsiniz belki, sunucuda durmasında bir zarar yok gibi.
Şimdi, yukarıda bir branchdan başka bir brancha push yapılabildiğinden bahsetmiştim. Ama pratikte bu bir kolaylık sağlamıyor(sonuçta diğer brancha geçtiğinizde yine fetch
+ merge
(veya sadece merge
) yapmanız lazım.
pull
ve fetch
+ merge
’den bahsetmek lazım. fetch
in yaptığı aslında sunucunuzdaki depodaki istediğiniz branchı depo-adi/branch-adi
adlı bir brancha çekmek. Daha sonra bunu branch-adi
ile merge etmek istiyorsanız git merge depo-adi/branch-adi
ile merge ediyorsunuz. İşte git pull depo-adi branch-adi
tam olarak bunu yapıyor.
➜ git-test git:(master) git fetch git-test master
From github.com:osa1/git-tests
* branch master -> FETCH_HEAD
➜ git-test git:(master) git merge git-test/master
Auto-merging test.markdown
CONFLICT (content): Merge conflict in test.markdown
Automatic merge failed; fix conflicts and then commit the result.
İşte şu anda yaptığım git pull
un yapacağının aynısı.
Yanlız burda anlamadığım bir nokta, eğer bu depo-adi/branch-adi
branchına geçersek şöyle bir mesaj alıyoruz:
➜ git-test git:(master) git checkout git-test/master
Note: checking out 'git-test/master'.
You are in 'detached HEAD' state. You can look around, make experimental
changes and commit them, and you can discard any commits you make in this
state without impacting any branches by performing another checkout.
If you want to create a new branch to retain commits you create, you may
do so (now or later) by using -b with the checkout command again. Example:
git checkout -b new_branch_name
HEAD is now at 53ea667... Merge remote branch 'git-test/master'
Ne demeye çalıştığını çözemedim.
Son olarak hayatımda gördüğüm en güzel şey(abarttım), eski commite geri dönme:
➜ git-test git:(branch3) git checkout 692832aa7a4a3a092e35f6955676be3c6e54e89e -b branch4
Switched to a new branch 'branch4'
Burdaki commit kodundan ilk başta bahsetmiştim. Yeni bir branch oluşturup eski commite dönüyorum.
commit -a
, daha önceden takipe aldığınız(git add
ile) dosyalardan değişiklik olanları otomatik olarak commite ekler. Teker teker yeniden git add
yapmanıza gerek kalmaz(ben ilk başta -a tüm dosyaları ekliyor sanıyordum mesela). commit -m
, commit mesajı için $EDITOR çevre değişkenindeki editorü çalıştırmak yerine(bu kısım sanırım sadece bash için geçerli) komut satırından mesaj girmenizi sağlar. Ben commitlerimi şöyle yapıyorum yani:
➜ git-test git:(master) git commit -a -m "mesaj"
Bu özellik yeni başlayanlar için çok kritik değil sanırım, ama bir arkadaşla bir proje üzerinde çalışırken(ne yaptığımız hakkında hiçbir fikrimiz yok tabi aehueah) git bize “git stash yap istersen” gibi uyarılar veriyordu. Biz de anlam veremiyorduk.
stash
ın olayı şuymuş, diyelim ki bir branchda değişiklikler yaptınız, bir bug gözünüze çarptı düzelteceksiniz, sadece o kısım düzelmiş olarak commit yapacaksınız. Hemen git stash save
ile o ana kadar yaptığınız commitlenmemiş değişiklikleri kaydediyorsunuz ve hemen son commitli haline dönüyor branch. Bugfix yapıp commit/pushluyorsunuz, sonra git stash pop
ile son kaydettiğiniz stash
e dönüyorsunuz. Birden fazla stash olabiliyor, git stash list
ile listeliyorsunuz. İşiniz bittiyse git stash drop
ile stashı siliyorsunuz falan. Henüz kullanma fırsatım olmadı, okuduklarımı yazıyorum. Kullandığımda örneklerle düzenleyebilirim.
Biraz dağınık oldu sanırım, amacım burda git’e veya sürüm kontrolüne yeni başlayanlara öğretmek değil de(o kadar bilmiyorum zaten), benim gibi bazı şeylerin ne kadar kolay/kullanışlı olduğunun farkında olmayanlara birşeyler göstermek ve kendime not düşmekt, o yüzden idare edin :P .