-
1. Başlangıç
- 1.1 Sürüm Denetimi
- 1.2 Git’in Kısa Tarihçesi
- 1.3 Git Nedir?
- 1.4 Komut Satırı
- 1.5 Git’i Yüklemek
- 1.6 Git’i İlk Defa Kurmak
- 1.7 Yardım Almak
- 1.8 Özet
-
2. Git Temelleri
-
3. Git Dalları
- 3.1 Dallar
- 3.2 Kısaca Dallandırma ve Birleştirme Temelleri
- 3.3 Dal Yönetimi
- 3.4 İş Akışı Dallandırması
- 3.5 Uzak Dallar
- 3.6 Yeniden Temelleme (rebase)
- 3.7 Özet
-
4. Bir Sunucuda Git Kurma
- 4.1 İletişim Kuralları (Protocols)
- 4.2 Bir Sunucuda Git Kurma
- 4.3 SSH Ortak Anahtarınızı Oluşturma
- 4.4 Sunucu Kurma
- 4.5 Git Cini (Daemon)
- 4.6 Akıllı HTTP
- 4.7 GitWeb
- 4.8 GitLab
- 4.9 Üçüncü Taraf Barındırma (Hosting) Seçenekleri
- 4.10 Özet
-
5. Dağıtık Git
- 5.1 Dağıtık İş Akışları
- 5.2 Projenin Gelişiminde Rol Almak
- 5.3 Bir Projeyi Yürütme
- 5.4 Özet
-
6. GitHub
- 6.1 Bir Projeye Katkıda Bulunmak
- 6.2 Proje Bakımı
- 6.3 Kurumsal Yönetim
- 6.4 GitHub’ı otomatikleştirme
- 6.5 Özet
-
7. Git Araçları
- 7.1 Düzeltme Seçimi
- 7.2 Etkileşimli İzlemleme (Staging)
- 7.3 Saklama ve Silme
- 7.4 Çalışmanızı İmzalama
- 7.5 Arama
- 7.6 Geçmişi Yeniden Yazma
- 7.7 Reset Komutunun Gizemleri
- 7.8 İleri Seviye Birleştirme
- 7.9 Rerere
- 7.10 Git’le Hata Ayıklama
- 7.11 Alt Modüller
- 7.12 Demetleme (Bundling)
- 7.13 Git Nesnesini Değiştirme
- 7.14 Kimlik Bilgisi Depolama
- 7.15 Özet
-
8. Git’i Özelleştirmek
- 8.1 Git Yapılandırması
- 8.2 Git Nitelikleri
- 8.3 Git Kancaları (Hooks)
- 8.4 Bir Örnek: Mecburi Git Politikası
- 8.5 Özet
-
9. Git ve Diğer Sistemler
- 9.1 İstemci Olarak Git
- 9.2 Git’e Geçiş
- 9.3 Özet
-
10. Dahili Git Ögeleri
- 10.1 Tesisat ve Döşeme (Plumbing ve Porcelain)
- 10.2 Git Nesneleri
- 10.3 Git Referansları
- 10.4 Packfiles
- 10.5 Refspec
- 10.6 Transfer Protokolleri
- 10.7 Bakım ve Veri Kurtarma
- 10.8 Ortam Değişkenleri
- 10.9 Özet
-
A1. Ek bölüm A: Diğer Ortamlarda Git
- A1.1 Görsel Arayüzler
- A1.2 Visual Studio ile Git
- A1.3 Visual Studio Code ile Git
- A1.4 Eclipse ile Git
- A1.5 Sublime Text ile Git
- A1.6 Bash ile Git
- A1.7 Zsh ile Git
- A1.8 PowerShell ile Git
- A1.9 Özet
-
A2. Ek bölüm B: Git’i Uygulamalarınıza Gömmek
- A2.1 Git Komut Satırı
- A2.2 Libgit2
- A2.3 JGit
- A2.4 go-git
- A2.5 Dulwich
-
A3. Ek bölüm C: Git Komutları
- A3.1 Kurulum ve Yapılandırma Komutları
- A3.2 Proje Oluşturma Komutları
- A3.3 Kısaca Poz (Snapshot) Alma
- A3.4 Dallandırma ve Birleştirme Komutları
- A3.5 Projeleri Paylaşma ve Güncelleme Komutları
- A3.6 İnceleme ve Karşılaştırma Komutları
- A3.7 Hata Ayıklama (Debugging) Komutları
- A3.8 Yamalama (Patching)
- A3.9 E-Posta Komutları
- A3.10 Harici Sistemler
- A3.11 Yönetim
- A3.12 Tesisat (Plumbing) Komutları
5.2 Dağıtık Git - Projenin Gelişiminde Rol Almak
Projenin Gelişiminde Rol Almak
Proje gelişiminde alınabilecek rolleri tanımlamanın temel zorluğu, bunu yapmanın birçok farklı yolunun olmasıdır. Git çok esnek olduğundan, insanlar bir proje üzerinde birçok farklı şekilde birlikte çalışabilirler ve her proje birbirinden farklı olduğu için, size projenin gelişiminde nasıl rol almanız gerektiğini dikte etmek yanlış olur. Aktif katkıcı sayısı, seçilen iş akışı, sizin işlenen katkılara erişiminiz ve muhtemel dış katkı yöntemi gibi bazı değişkenler bu süreci etkiler.
İlk değişken aktif katkıcı sayısıdır: bu projeye kaç aktif katkıcı, ne sıklıkta, kod katkısında bulunuyor? Çoğu zaman, günde birkaç katkı işleyen, iki veya üç geliştirici olabilir hatta bazı durağan projeler için daha azdır. Daha büyük şirketler veya projeler için, binlerce geliştirici olabilir ve her gün yüzlerce veya binlerce katkı işlenebilir. Katkıda bulunan geliştirici sayısı arttıkça, kodunuzun temiz şekilde uygulanması veya kolayca birleştirilebilmesi konusunda daha fazla sorunla karşılaşırsınız. Gönderdiğiniz değişiklikler, siz çalışırken veya değişiklikleriniz onaylanmayı ve uygulanmayı beklerken, birleştirilen çalışmalar nedeniyle artık uyumsuz hale gelebilir veya ciddi şekilde bozulabilir.
Sonraki değişken: projenin kullandığı iş akışıdır. Her geliştiricinin ana kod satırına eşit yazma erişimine sahip olduğu iş akışı, merkezi mi yoksa dağıtık mıdır? Projede, tüm yamaları kontrol eden bir bakım veya birleştirme yöneticisi var mı? Tüm yamalar gözden geçirilip ve onaylanıyor mu? Bu süreçte yer alıyor musunuz? Diktatör-yaver sistemi var mı ve çalışmanızı önce onlara sunmanız mı gerekiyor?
Tüm bu sorular, bir projeye nasıl etkili bir şekilde katkıda bulunacağınızı ve sizin için tercih edilen veya uygulanabilir olan iş akışlarının neler olduğunu etkileyebilir. Bu soruların bazı yönlerini, basitten daha karmaşığa doğru bir dizi kullanım durumuyla ele alacağız. Bu örneklerden yola çıkarak, ihtiyacınız olan belirli iş akışlarını oluşturabileceğinizi umuyoruz.
Katkı Rehberi
Özel kullanım durumlarını incelemeye başlamadan önce, katkı mesajları hakkında kısa bir not verelim.
Katkı oluşturmak için iyi bir kılavuza sahip olmak ve ona uygun davranmak, Git ile çalışmayı ve başkalarıyla işbirliği yapmayı çok daha kolay hale getirir.
Git projesi, yama göndermek amacıyla nasıl iyi bir katkı oluşturacağınız hakkında kullanışlı ipuçları sunan kullanışlı bir belgeye sahiptir.
Onu Git kaynak kodunda Documentation/SubmittingPatches
dosyasında bulabilirsiniz.
Öncelikle, gönderilerinizde boşluk (whitespace) hataları olmamalıdır.
Git, bunu kontrol etmek için kolay bir yol sağlar: Git’in olası boşluk hataların tanımlayıp size listelemesi için, katkılamadan önce git diff --check
komutunu çalıştırın.
git diff --check
çıktısı.Eğer bunu katkılamadan önce çalıştırırsanız, diğer geliştiricileri rahatsız edebilecek boşluk sorunlarını katkılamak üzere olduğunuzu görebilirsiniz.
Sonraki adım, her bir katkıyı mantıksal olarak ayrı bir değişim seti olarak ayarlamaktır.
Mümkünse, değişikliklerinizi sindirilebilir hale getirmeye çalışın: bütün hafta sonu beş farklı sorun üzerinde kod yazıp, Pazartesi günü hepsini tek bir devasa katkı olarak göndermeyin.
Hafta sonu boyunca hiç katkı işlemeseniz bile, pazartesi günü çalışmanızı her konuya (iş paketine) -faydalı bir katkı mesajı da içeren- en az bir katkı olacak şekilde ayırın.
Değişikliklerden bazıları aynı dosyayı değiştiriyorsa, dosyaları kısmen aşamalandırmak için git add --patch
kullanmaya çalışın (Etkileşimli İzlemleme (Staging) bölümünde detaylı olarak ele alınmıştır).
Tüm değişiklikler bir şekilde eklendikten sonra, ister tek katkıda işleyin ister beş, dalın ucu üzerinde yer alan nihai proje pozu aynıdır.
Bu yüzden değişikliklerinizi inceleyen diğer geliştiricilerin işlerini kolaylaştırmaya çalışın.
Bu yaklaşım, daha sonra bir değişiklik setini çıkarmak veya geri almak istediğinizde de işleriniz büyük ölçüde kolaylaştırır. Geçmişi Yeniden Yazma bölümünde geçmişi değiştirme ve dosyaları etkileşimli olarak aşamalamayla ilgili birçok faydalı ipucu bulabilirsiniz. Bu araçları kullanarak, çalışmanızı başka birine göndermeden önce, temiz ve anlaşılabilir bir katkı geçmişi oluşturmaya yardımcı olun.
Akılda tutulması gereken son şey ise katkı mesajıdır. Kaliteli bir katkı mesajı oluşturma alışkanlığı, Git’i kullanmayı ve işbirliği yapmayı çok daha kolay hale getirir. Genel bir kural olarak mesajlarınız: 50 karakteri geçmeyecek şekilde, değişiklik setini özetleyen tek bir satırla başlamalı ve bir satır boşluk bıraktıktan sonra daha ayrıntılı bir açıklama içermelidir. Ayrıntılı açıklamada: değişikliğinizi neden yaptığınızı, ve uygulamanızın önceki davranışla nasıl farklılıklar içerdiğini açıklamanız gerekir. Bu takip edebileceğiniz sağlam bir yönergedir. Katkı mesajınızı emir kipiyle yazın: "Hata düzeltildi" veya "Düzeltilmiş Hata" yerine "Hata düzelt" gibi. Tim Pope tarafından yazılan şablonu inceleyebilirsiniz:
Büyük harfle başlayan, kısa (50 karakterden az) özet
Gerekirse, daha detaylı açıklayıcı metin.
Yaklaşık 72 civarı karakterle anlatın.
Bazı bağlamlarda, ilk satır aynı bir e-postadaki konu kısmı ve geri kalan kısım da mesaj gövdesi gibi kabul edilir.
Özet ile detay arasındaki boş satır (açıklamayı tamamen atlamazsanız) kritik önemdedir.
Eğer ikisini birleştirirseniz "rebase" gibi araçlar karışıklık yaşayabilir.
Katkı mesajınızı emir kipiyle yazın: "Hata düzeltildi" veya "Hatayı önlüyor" yerine "Hataları düzelt" gibi ifadeler kullanın.
Bu kural, `git merge` ve `git revert` gibi komutlarla oluşturulan katkı mesajlarıyla eşleşir.
Daha ileri açıklamalar boş satırlardan sonra gelir.
- Madde işaretleri (-, *, vb) uygundur
- Genellikle madde işareti olarak tire (-) veya yıldız (*) kullanılır, ardından tek bir boşluk bırakılır ve maddeler arasında boş satırlar bulunur. (Bu kısımda anlatılan kurallar ortak görüşe göre değişebilir.)
- Aynı maddede ikinci satıra geçerken bir girinti kullanılır.
Eğer tüm katkı mesajlarınız bu modele uygunsa, işbirliği yaptığınız geliştiriciler ve sizin için her şey çok daha kolay olacaktır.
Git projesinin düzgün biçimlendirilmiş katkı mesajları bulunmaktadır (ne kadar güzel biçimlendirilmiş bir proje-katkı geçmişine sahip olduğunuzu görmek için git log --no-merges
komutunu çalıştırabilirsiniz).
Not
|
Dediğimizi yap, yaptığımızı değil!
Bu kitaptaki birçok örnekte olduğu gibi, sırf kısa kesmek adına, böyle güzel biçimlendirilmiş katkı mesajları yazmamış olabiliriz. Uzun ve güzel mesajlar yazmak yerine, hemen Yani: dediğimi yapın, yaptığımı yapmayın! |
Küçük Özel Ekipler
Muhtemelen karşılaşacağınız en basit kurulum, sadece birkaç geliştiriciyle yapacağınız özel bir projedir. Bu bağlamda "özel", kapalı kaynaklı anlamına gelir, yani dış dünyadan erişilemez. Siz ve diğer geliştiricilerin hepsi repoya itme erişimine sahipsiniz.
Bu geliştirme ortamında, Subversion veya başka bir merkezi sistem kullandığınızdaki gibi bir iş akışı takip edebilirsiniz.
Çevrimdışı katkı işleme ve çok daha basit dallandırma ve birleştirme gibi avantajlara sahip olursunuz, ancak iş akışı yine de çok benzerdir.
Temel fark, birleştirmelerin sunucu üzerinde ve katkı anında olması yerine, istemci tarafında gerçekleşmesidir.
İki geliştiricinin paylaşılan bir repoda birlikte çalışmaya başladığı durumun nasıl görüneceğine bakalım.
İlk geliştirici, John, repoyu kopyalar, bir değişiklik yapar ve yerel olarak katkı işler.
(Örnekleri kısaltmak için, protokol mesajları ...
şeklinde yazılmıştır.)
# John's Machine
$ git clone john@githost:simplegit.git
Cloning into 'simplegit'...
...
$ cd simplegit/
$ vim lib/simplegit.rb
$ git commit -am 'remove invalid default value'
[master 738ee87] remove invalid default value
1 files changed, 1 insertions(+), 1 deletions(-)
İkinci geliştirici, Jessica, aynı şeyi yapar: repoyu koypalar ve bir değişiklik katkılar:
# Jessica's Machine
$ git clone jessica@githost:simplegit.git
Cloning into 'simplegit'...
...
$ cd simplegit/
$ vim TODO
$ git commit -am 'add reset task'
[master fbff5bc] add reset task
1 files changed, 1 insertions(+), 0 deletions(-)
Şimdi Jessica çalışmasını sorunsuz bir şekilde sunucuya gönderiyor:
# Jessica's Machine
$ git push origin master
...
To jessica@githost:simplegit.git
1edee6b..fbff5bc master -> master
Yukarıdaki çıktının son satırı, itme işlemi ardından yararlı bir dönüş mesajı gösterir.
Temel format, <oldref>..<newref> fromref -> toref
şeklindedir, burada oldref
eski referansı, newref
yeni referansı, fromref
gönderilen yerel referansın adını ve toref
güncellenen uzak referansın adını ifade eder.
İleride de benzer çıktılar göreceğiniz için, bu mevzuda temel kavrayışınızın olması, repoların çeşitli durumlarını anlamanıza yardımcı olacaktır.
git-itme linkinde daha fazla ayrıntı bulunmaktadır.
Örneğimize devam edersek, bir süre sonra John bazı değişiklikler yapar, bunları yerel reposuna kaydeder ve aynı sunucuya göndermeye çalışır:
# John's Machine
$ git push origin master
To john@githost:simplegit.git
! [rejected] master -> master (non-fast forward)
error: failed to push some refs to 'john@githost:simplegit.git'
Bu durumda, John’un gönderimi, Jessica’nın kendi değişikliklerini önceden göndermesinden dolayı başarısız olur. Eğer Subversion kullanıyorsanız bu özellikle önemlidir, çünkü iki geliştiricinin aynı dosyayı düzenlemediğini fark edeceksiniz. Subversion’da farklı dosyalar düzenlenirse sunucu otomatik olarak böyle bir birleştirme yapar, ancak Git’te öncelikle geliştiricilerin yerel olarak birleştirme yapmaları gerekir. Yani, John’un önce Jessica’nın yukarı akış (upstream) değişikliklerini alıp bunları yerel reposuna birleştirmesi gerekmektedir.
İlk adım olarak, John Jessica’nın çalışmasını alır (fetch
sadece Jessica’nın yukarı akış çalışmasını alır, henüz John’un çalışmasına birleştirmez):
$ git fetch origin
...
From john@githost:simplegit
+ 049d078...fbff5bc master -> origin/master
Bu noktada, John’un yerel reposu şuna benzer:
Şimdi John, çektiği Jessica’nın çalışmasını kendi yerel çalışmasına birleştirebilir:
$ git merge origin/master
Merge made by the 'recursive' strategy.
TODO | 1 +
1 files changed, 1 insertions(+), 0 deletions(-)
Eğer bu yerel birleştirme sorunsuz bir şekilde gerçekleşirse, John’ın güncellenmiş geçmişi artık şöyle görünecektir:
origin/master
'a birleştirme sonrası John’un reposu.Bu noktada, Jessica’nın çalışmalarının kendisininkini etkilemediğinden emin olmak için, John bu yeni kodu test etmek isteyebilir ve her şeyin yolundaysa, sonunda birleştirilmiş yeni çalışmasını sunucuya itebilir:
$ git push origin master
...
To john@githost:simplegit.git
fbff5bc..72bbc59 master -> master
Sonuçta, John’ın katkı geçmişi şöyle görünecektir:
origin
sunucusuna ittikten sonra John’un katkı geçmişi.Bu arada, Jessica issue54
adında yeni bir tematik dal oluşturdu ve bu dala üç katkı işledi.
Henüz John’un değişikliklerini çekmediği için, katkı geçmişi şöyle görünüyor:
Jessica birden John’ın sunucuya yeni bir değişiklik ittiğini öğrenir ve ona bir göz atmak ister: böylece henüz sahip olmadığı tüm yeni içerikleri sunucudan alabilecektir:
# Jessica's Machine
$ git fetch origin
...
From jessica@githost:simplegit
fbff5bc..72bbc59 master -> origin/master
Bu komutla, John’ın en son yüklediği çalışmayı indirir. Jessica’nın geçmişi şimdi şöyle görünmektedir:
Jessica tematik dalının hazır olduğunu düşünüyor, ancak itme yapabilmek için, John’dan aldığı hangi bölümü kendi çalışmasına birleştirmesi gerektiğini öğrenmek istiyor.
Bunu öğrenmek için git log
komutunu çalıştırır:
$ git log --no-merges issue54..origin/master
commit 738ee872852dfaa9d6634e0dea7a324040193016
Author: John Smith <jsmith@example.com>
Date: Fri May 29 16:01:27 2009 -0700
remove invalid default value
issue54..origin/master
sözdizimi, Git’e sadece ikinci dalda (origin/master
) bulunan ve ilk dalda (issue54
) bulunmayan katkıları göstermesini isteyen bir günlük (log kaydı) süzgecidir.
Bu sözdizimini Katkı Aralığı bölümünde detaylı olarak ele alacağız.
Yukarıdaki çıktıdan, John’un işlediği ama Jessica’nın yerel çalışmasına birleştirmediği tek bir katkı olduğunu görebiliriz.
Eğer Jessica origin/master
'a birleştirirse, bu onun yerel çalışmasını değiştirecek olan tek katkı olacaktır.
Jessica artık tematik çalışmasını ana dalına birleştirip, John’un çalışmasını (origin/master
) da ana dalına birleştirdikten sonra tekrar sunucuya gönderebilir.
Jessica issue54
tematik dalındaki tüm çalışmalarını katkıladıktan sonra, bütün bu çalışmaları birleştirmek için ana dalına (master) geçiş yapar:
$ git checkout master
Switched to branch 'master'
Your branch is behind 'origin/master' by 2 commits, and can be fast-forwarded.
Jessica önce origin/master
veya issue54
'ü birleştirebilir: ikisi de kökdalda olduğu için sıra önemli değildir.
Hangi sırayı seçerse seçsin, son poz aynı olmalıdır (sadece tarih farklı olacaktır).
Jessica, önce issue54
dalını birleştirmeyi tercih eder:
$ git merge issue54
Updating fbff5bc..4af4298
Fast forward
README | 1 +
lib/simplegit.rb | 6 +++++-
2 files changed, 6 insertions(+), 1 deletions(-)
Herhangi bir sorun yoktur ve gördüğünüz gibi, bu normal bir "ileri sarma" birleştirmesidir.
Jessica şimdi John’ın önceden alınmış ve origin/master
dalında beklemekte olan çalışmasını birleştirme sürecini tamamlar:
$ git merge origin/master
Auto-merging lib/simplegit.rb
Merge made by the 'recursive' strategy.
lib/simplegit.rb | 2 +-
1 files changed, 1 insertions(+), 1 deletions(-)
Her şey temiz bir şekilde birleştirildi ve Jessica’nın geçmişi şimdi şöyle görünüyor:
Artık origin/master
Jessica’nın master
dalından erişilebilir durumda olduğuna göre Jessica değişikliklerini itebilir durumda olmalı (tabi John bu arada daha fazla değişiklik yapıp itmemişse):
$ git push origin master
...
To jessica@githost:simplegit.git
72bbc59..8059c15 master -> master
Her geliştirici birkaç kez katkı işlemiş ve birbirlerinin çalışmasını başarılı bir şekilde birleştirmiştir.
Bu, en basit iş akışlarından biridir.
Bir süre çalışırsınız (genellikle bir tematik dalda) ve calışmanız birleştirilmeye hazır olduğunda bunu master
dalınıza birleştirirsiniz.
Bu çalışmayı paylaşmak isterseniz, yeni bir değişiklik varsa master
dalınızı origin/master
üzerinden çekip (fetch) birleştirirsiniz (merge) ve son olarak sunucudaki master
dala itersiniz.
Bu işlem genellikle şöyle olur:
Özel Yönetilen Ekipler
Sıradaki senaryoda, daha büyük bir özel grupta projede yer alanların rollerini inceleyeceğiz. Küçük ekiplerden her birinin, büyük bir projenin sadece bir kısmı (mesela bir uygulamanın tek bir özelliği) üzerinde işbirliği yaptığı ve sonra bu ekip bazlı çalışmaların üçüncü bir tarafça birleştirildiği ortamlarda nasıl çalışacağınızı öğreneceksiniz.
Diyelim ki John ve Jessica bir özellik (bunu featureA
olarak adlandıralım) üzerinde birlikte çalışırken, Jessica aynı zamanda Josie adındaki üçüncü bir geliştirici ile birlikte, ikinci bir özellik (bu da featureB
olsun) üzerinde de çalışıyor.
Bu senaryoda şirket, birim ekiplerce geliştirilen çalışmaların sadece belirli bazı mühendisler tarafından birleştirilebildiği bir birleşim-yöneticisi ağ akışı kullanıyor ve ana reponun master
dalı sadece bu mühendisler tarafından güncellenebiliyor.
Burada, tüm çalışmalar ekip temelli dallarda yapılır ve daha sonra birleştiriciler tarafından bir araya getirilebilir.
Hadi her iki özellik üzerinde ve iki farklı geliştiriciyle eşzamanlı çalışırken Jessica’nın iş akışını takip edelim.
Varsayalım ki reposunu zaten kopyalamış ve ilk olarak featureA
üzerinde çalışmaya karar vermiş olsun.
Özelliğe yeni bir dal oluşturur ve burada bazı çalışmalar yapar:
Önce featureA
için yeni bir dal oluşturur ve orada bazı çalışmalar yapar:
# Jessica's Machine
$ git checkout -b featureA
Switched to a new branch 'featureA'
$ vim lib/simplegit.rb
$ git commit -am 'add limit to log function'
[featureA 3300904] add limit to log function
1 files changed, 1 insertions(+), 1 deletions(-)
Bu noktada, çalışmalarını John ile paylaşması gerektiği için featureA
dalındaki katkıların sunucuya iter.
Jessica’nın master
dalına itme erişimi olmadığından (yalnızca birleştiricilerin yetkisi vardı), John ile işbirliği yapabilmek için çalışmalarını başka bir dala itmesi gerekiyor:
$ git push -u origin featureA
...
To jessica@githost:simplegit.git
* [new branch] featureA -> featureA
Jessica John’a: çalışmalarını featureA
adında bir dalda ittiğini ve isterse bakabileceğini söylemek için bir e-posta gönderir.
Jessica John’dan geri bildirim beklerken, Josie ile featureB
üzerinde çalışmasına başlamaya karar verir.
Başlamak için, sunucunun master
dalından temelleyerek tematik bir dal açar:
# Jessica's Machine
$ git fetch origin
$ git checkout -b featureB origin/master
Switched to a new branch 'featureB'
Ardından featureB
dalında birkaç katkı işler:
$ vim lib/simplegit.rb
$ git commit -am 'made the ls-tree function recursive'
[featureB e5b0fdc] made the ls-tree function recursive
1 files changed, 1 insertions(+), 1 deletions(-)
$ vim lib/simplegit.rb
$ git commit -am 'add ls-files'
[featureB 8512791] add ls-files
1 files changed, 5 insertions(+), 0 deletions(-)
Jessica’nın reposu artık şöyle görünüyor:
Jessica çalışmasını itmeye hazırdır, ancak Josie’den, içinde öncel featureB
çalışmalarını barındıran featureBee
adında bir dalın, daha önceden sunucuya itilmiş olduğunu bildiren e-posta alır.
Jessica’nın kendi çalışmasını sunucuya göndermeden önce bu değişiklikleri kendi mevcut çalışmasıyla birleştirmesi gerekmektedir. Jessica önce Josie’nin değişikliklerini git fetch
komutu kullanarak getirir:
$ git fetch origin
...
From jessica@githost:simplegit
* [new branch] featureBee -> origin/featureBee
Jessica’nın halen featureB
dalında olduğunu varsayarsak, Josie’nin çalışmasını bu dal ile git merge
kullanarak hemen birleştirebilir:
$ git merge origin/featureBee
Auto-merging lib/simplegit.rb
Merge made by the 'recursive' strategy.
lib/simplegit.rb | 4 ++++
1 files changed, 4 insertions(+), 0 deletions(-)
Jessica şimdi bu birleştirilmiş "featureB" çalışmasını hepsini sunucuya geri itmeyi düşünüyor, ancak kendi featureB
dalını doğrudan itmek istemiyor.
Zaten Josie’nin bir kökdal olarak başlattığı featureBee
mevcut olduğundan, Jessica oraya itmek istiyor.
Ve bunu şöyle yapıyor:
$ git push -u origin featureB:featureBee
...
To jessica@githost:simplegit.git
fba9af8..cd685d1 featureB -> featureBee
Bu, bir refspec olarak adlandırılır.
Git refspec’lerin detaylı bir incelemesi ve onunla daha başka neler yapılacağını görmek için Refspec bağlantısına bakabilirsiniz.
Ayrıca -u
bayrağına da dikkat edin: bu --set-upstream` ifadesinin kısaltmasıdır ve dalları daha kolay itme ve çekme işlemleri için yapılandırır.
Jessica ansızın John’dan, beraber çalıştıkları featureA
dalında, bazı değişiklikler yaptığını belirten bir e-posta alır ve Jessica’dan bunlara bakmasını ister.
Jessica tekrardan John’un en son çalışmasını da içeren sunucudan tüm yeni içeriği getirmek için basit bir git fetch
komutu çalıştırır:
$ git fetch origin
...
From jessica@githost:simplegit
3300904..aad881d featureA -> origin/featureA
Jessica, yeni alınan featureA
dalının içeriğini kendi yerel kopyasıyla karşılaştırarak, John’un yeni çalışmasının günlüğünü görüntüleyebilir:
$ git log featureA..origin/featureA
commit aad881d154acdaeb2b6b18ea0e827ed8a6d671e6
Author: John Smith <jsmith@example.com>
Date: Fri May 29 19:57:33 2009 -0700
changed log output to 30 from 25
Jessica gördüğü işi beğenir ve John’un yeni çalışmasını yerel featureA
dalına birleştirmek ister:
$ git checkout featureA
Switched to branch 'featureA'
$ git merge origin/featureA
Updating 3300904..aad881d
Fast forward
lib/simplegit.rb | 10 +++++++++-
1 files changed, 9 insertions(+), 1 deletions(-)
Son olarak, Jessica muhtemelen tüm bu birleştirilen içeriğe birkaç küçük değişiklik eklemek isteyecektir.
Bu yüzden, gerekli değişiklikleri yapar, bunları yerel featureA
dalına katkılar ve sonucu sunucuya geri iter.
$ git commit -am 'small tweak'
[featureA 774b3ed] small tweak
1 files changed, 1 insertions(+), 1 deletions(-)
$ git push
...
To jessica@githost:simplegit.git
3300904..774b3ed featureA -> featureA
Jessica’nın katkı geçmişi şöyle görünmektedir:
Jessica, Josie ve John, birleşim yöneticilerine, featureA
ve featureBee
adlı dalların ana gövdeye birleştirilmeye hazır olduğunu bildirirler.
Bu dallar ana gövdeye birleştirildikten sonra yapılacak bir çekme işlemi, yeni birleştirme katkısın indirecek ve geçmiş şu şekilde görünecektir:
Birçok ekibin Git’e geçme sebebi, paralel işleyen farklı dallar üzerindeki eşzamanlı çalışmaları sürecin sonunda rahatça birleştirme yeteneğidir. Bir takımın daha küçük alt gruplarının, tüm ekibi dâhil etmek veya engellemek zorunda kalmadan uzak dallar aracılığıyla işbirliği yapabilme yeteneği, Git’in büyük bir avantajıdır. Burada gördüğünüz iş akışı bunu göstermektedir:
Çatallanmış Açık Projeler
Açık (herkese açık kaynak kodlu) projelere katkı sağlamak biraz farklıdır. Projedeki dalları doğrudan güncelleme izniniz olmadığı için, çalışmanızı yürütücülere (maintainer) başka bir şekilde ulaştırmalısınız. Bu ilk örnek, çatal oluşturma imkanı sunan Git barındırma siteleri üzerinden katkı sağlama sürecini açıklar. GitHub, BitBucket, repo.or.cz ve benzeri birçok barındırma sitesi bunu destekler ve birçok proje yürütücüsü bu tarz bir katkı bekler. Sonraki bölüm, katkı sağlanan yamaların e-posta aracılığıyla kabul edildiği projeleri ele alır.
İlk olarak ana repoyu kopyalamanız gerekmektedir. Ardından katkıda bulunmayı planladığınız yama veya yama dizisi için bir tematik dal oluşturacak ve çalışmanızı burada yapacaksınız. Temel olarak bu sıralama şöyle görünür:
$ git clone <url>
$ cd project
$ git checkout -b featureA
... work ...
$ git commit
... work ...
$ git commit
Not
|
İşinizi tek katkı işleyecek şekilde sıkıştırmak veya yamayı inceleyecek bakım görevlisinin işini kolaylaştırmak amacıyla işi katkılar halinde yeniden düzenlemek için |
Daldaki çalışmanız bittiğinde ve bunu yürütücülere katkı olarak göndermeye hazır olduğunuzda, orijinal proje sayfasına gidin ve "Fork" düğmesine tıklayarak, kendi yazılabilir çatalınızı oluşturun.
Ardından, bu repo URL’sini yerel reponuzun yeni bir uzak reposu olarak eklemelisiniz.
Hadi ona myfork
adını verelim:
$ git remote add myfork <url>
Sonra, yeni çalışmanızı bu repoya göndermeniz gerekir.
Çalıştığınız tematik dalınızı çatallamış olduğunuz depoya göndermek, onu master dalınıza birleştirip ardından da itmekten daha kolaydır.
Bunun nedeni, çalışmanızın kabul edilmemesi veya ayıklanması (cherry-pick) durumunda ana dalınızı geri sarmanız gerekmemesidir (Git cherry-pick
işlemi Temelleme ve Ayıklama (Cherry-Picking) İş Akışları bölümünde daha ayrıntılı olarak ele alınmıştır).
Eğer yürütücüler çalışmanızı birleştirir, yeniden temeller veya ayıklarsa, çalışmanızı onların reposundan çekerek alabilirsiniz.
Her durumda, çalışmanızı şu şekilde itebilirsiniz:
$ git push -u myfork featureA
Çalışmanız reponun size ait çatalına itildikten sonra, orjinal projenin yürütücülerini çalışmanızı birleştirmelerini istediğinize dair bilgilendirmelisiniz.
Bu genellikle bir çekme isteği (pull request) olarak adlandırılır ve genellikle web sitesi üzerinden oluşturulur (GitHub’ın kendi "Çekme İsteği" mekanizması vardır, bu konuyu GitHub bölümünde ele alacağız) ya da git request-pull
komutunu çalıştırıp ardından üretilen çıktıyı proje yürütücüsüno manuel olarak e-posta yoluyla gönderebilirsiniz.
git request-pull
komutu, tematik dalınızı çekmek istediğiniz temel dalı ve çekilmesini istediğiniz Git deposunun URL’sini alır ve çekilecek tüm değişikliklerin bir özetini üretir.
Örneğin, Jessica’nın John’a bir çekme isteği göndermek istediğini ve yeni gönderdiği tema dalında iki değişiklik yaptığını varsayalım, bu durumda şunu çalıştırabilir:
$ git request-pull origin/master myfork
The following changes since commit 1edee6b1d61823a2de3b09c160d7080b8d1b3a40:
Jessica Smith (1):
added a new function
are available in the git repository at:
git://githost/simplegit.git featureA
Jessica Smith (2):
add limit to log function
change log output to 30 from 25
lib/simplegit.rb | 10 +++++++++-
1 files changed, 9 insertions(+), 1 deletions(-)
Katkıların özetini gösteren, çalışmanın nereden dallandığını ve yeni çalışmanın nereden çekileceğini belirten bu çıktı, yürütücüye gönderilebilir.
Yürütücü olmadığınız bir projede, genellikle origin/master
ı izleyen master
gibi bir dalın bulunması ve çalışmanızı, reddedilmesi durumunda kolayca silebileceğiniz, tematik dallar üzerinde yapmanız daha kolay olur.
İş paketlerinin tematik dallara — kök daldan izole şekilde — kısıtlanması, çalıştığınız süre zarfında ana repo ucunun ilerlemiş olması ve sizin katkılarınızın artık temiz bir şekilde uygulanamaması durumunda da işinizi yeniden düzenlemenizi kolaylaştırır.
Örneğin, projeye ikinci bir iş başlığı göndermek istiyorsanız, zaten yukarı itilmiş olan tematik dalda çalışmaya devam etmeyin; ana repo master
dalından tekrar başlayın:
$ git checkout -b featureB origin/master
... work ...
$ git commit
$ git push myfork featureB
$ git request-pull origin/master myfork
... email generated request pull to maintainer ...
$ git fetch origin
Artık her bir başlığımız, yama kuyruğunda (patch queue) olduğu gibi: yeniden yazabileceğiniz, temelleyebileceğiniz ve başka konu başlıklarından bağımsız ve birbirini etkilemeden değiştirebileceğiniz bir iş ambarı içinde bulunuyor. Şunun gibi:
featureB
çalışmasının öncel katkı geçmişi.Diyelim ki, yürütücü birçok başka yamayı çekmiş ve sizin ilk dalınızı çekmeyi de denemiş, ancak artık temiz bir şekilde birleşmiyor.
Bu durumda, bu dalı origin/master
'ın üzerine temellemeyi deneyebilir ve yürütücü için çatışmaları çözüp, ardından değişikliklerinizi yeniden gönderebilirsiniz.
$ git checkout featureA
$ git rebase origin/master
$ git push -f myfork featureA
Bu, şimdi geçmişinizi featureA
çalışmasından sonra katkı geçmişi. gibi yeniden yazar.
featureA
çalışmasından sonra katkı geçmişi.Dalı yeniden temellendirdiniz; bu yüzden sunucudaki featureA
dalını, kendi soyundan gelmeyen bir katkıyla değiştirebilmek için itme komutunuza -f
bayrağı eklemelisiniz.
Başka bir alternatif ise, bu yeni çalışmayı sunucuda farklı (mesela featureAv2
olarak adlandırılmış) bir dala itmektir.
Bir başka olası senaryoya bir göz atalım: yürütücü ikinci dalınızdaki çalışmayı inceledi ve yaklaşımınızı beğendi, ancak uygulamadi bir detayı değiştirmenizi istiyor.
Bu fırsatı, çalışmanın projenin mevcut master
dalına dayandırılmasını sağlamak için de kullanacaksınız.
Mevcut origin/master
dalına dayanan yeni bir dal başlatırsınız; burada featureB
değişikliklerini birleştirir, çatışmaları çözer, uygulama değişikliğini yapar ve ardından bunu yeni bir dal olarak itersiniz:
$ git checkout -b featureBv2 origin/master
$ git merge --squash featureB
... change implementation ...
$ git commit
$ git push myfork featureBv2
--squash
seçeneği birleştirilen dal üzerindeki tüm çalışmayı alır ve bunu bir birleştirme katkısı oluşturmadan - ama gerçek bir birleştirme gerçekleştiğinde oluşan bir repo durumu üretecek şekilde - bir değişiklik kümesine sıkıştırır.
Bunun anlamı, gelecekteki birleştirme katkınızın yalnızca bir önceli olmasıdır.
Ayrıca, diğer dalın tüm değişikliklerini tanıtmanıza ve ardından yeni bir katkı işlemine geçmeden önce daha fazla değişiklik yapmanıza izin verir
Ek olarak, varsayılan birleştirme işlemi durumunda, birleştirme katkısını geciktirmek için --no-commit
seçeneğini kullanabilirsiniz.
Bu noktada, istenen değişiklikleri yaptığınızı ve bu değişikliklere featureBv2
dalından ulaşabileceklerini proje yürütücüsüne bildirebilirsiniz.
featureBv2
çalışmasının ardından katkı geçmişi.E-posta Üzerinden Açık Projeler
Çok sayıda proje, yamaları kabul etmek için belirlenmiş yönergeler kullanır. Bunlar birbirinden farklılık göstereceği için, her proje için bu yönergeleri kontrol etmeniz gerekecektir. Yamaları geliştirici posta listesi üzerinden kabul eden birkaç eski ve büyük proje olduğundan, şimdi bir örnekle bunu ele alacağız.
Bu iş akışı, bir önceki kullanım durumuna benzer; üzerinde çalıştığınız her yama serisi için tematik dallar oluşturursunuz. Fark, onları projeye nasıl gönderdiğinizdedir. Projeyi çatallayıp kendi yazılabilir sürümünüze itmek yerine, her bir katkı serisinin e-posta sürümlerini oluşturur ve geliştirici posta listesine e-posta olarak gönderirsiniz:
$ git checkout -b topicA
... work ...
$ git commit
... work ...
$ git commit
Şimdi posta listesine göndermek istediğiniz iki katkınız var.
Geliştirici listesine e-posta olarak gönderebileceğiniz mbox biçimli dosyalar oluşturmak için git format-patch
komutu kullanırsınız.
Bu komut her katkıyı; ilk satırı e-postanın başlık kısmına ve geri kalan mesaj ve yama da e-postanın gövde kısmına denk düşen bir e-posta’ya dönüştürür.
Bu yöntemin güzel yanı: format-patch
ile oluşturulan bir e-postadan yama uygulayarak, tüm katkı bilgilerinin düzgün bir şekilde korunmasıdır.
$ git format-patch -M origin/master
0001-add-limit-to-log-function.patch
0002-changed-log-output-to-30-from-25.patch
format-patch
komutu oluşturduğu yama dosyalarının isimlerini yazdırır.
-M
bayrağı Git’e yeniden adlandırmaları aramasını söyler.
Dosyalar en sonda şöyle görünür:
$ cat 0001-add-limit-to-log-function.patch
From 330090432754092d704da8e76ca5c05c198e71a8 Mon Sep 17 00:00:00 2001
From: Jessica Smith <jessica@example.com>
Date: Sun, 6 Apr 2008 10:17:23 -0700
Subject: [PATCH 1/2] add limit to log function
Limit log functionality to the first 20
---
lib/simplegit.rb | 2 +-
1 files changed, 1 insertions(+), 1 deletions(-)
diff --git a/lib/simplegit.rb b/lib/simplegit.rb
index 76f47bc..f9815f1 100644
--- a/lib/simplegit.rb
+++ b/lib/simplegit.rb
@@ -14,7 +14,7 @@ class SimpleGit
end
def log(treeish = 'master')
- command("git log #{treeish}")
+ command("git log -n 20 #{treeish}")
end
def ls_tree(treeish = 'master')
--
2.1.0
Ayrıca, katkı mesajında görünmesini istemediğiniz e-posta listesi için daha fazla bilgi ekleyerek bu yama dosyalarını düzenleyebilirsiniz.
Eğer ---
satırı ve yama başlangıcı (diff --git
satırı) arasına metin eklerseniz, geliştiriciler bunu okuyabilir; ancak bu içerik yamalama işlemi tarafından yok sayılır.
Bir posta listesine e-posta göndermek için, ya dosyayı e-posta içeriğinize kopyala-yapıştır yoluyla ekler ya da komut satırı aracılığıyla gönderebilirsiniz.
Metni yapıştırmak - özellikle yeni satır ve diğer boşlukları uygun şekilde korumayan "akıllı" istemcilerde - biçimlendirme sorunlarına neden olabilir.
Neyse ki Git’in sağladığı, doğru biçimlendirilmiş yamaları IMAP aracılığıyla göndermenize yardımcı olacak bir araç, size kolaylık sağlayabilir.
En iyi bildiğimiz e-posta aracısı olan Gmail üzerinden bir yamanın nasıl gönderileceğini size göstereceğiz.
Git kaynak kodunda yer alan Documentation/SubmittingPatches
dosyasının sonunda, farklı e-posta programları için yazılmış detaylı yönergeleri okuyabilirsiniz.
İlk olarak, ~/.gitconfig
dosyanızdaki imap bölümünü yapılandırmanız gerekir.
Her bir değeri ayrı ayrı git config
komutlarıyla ayarlayabilir veya bunları manuel olarak ekleyebilirsiniz; ancak sonunda yapılandırma dosyanız şuna benzer bir şekilde olmalıdır:
[imap]
folder = "[Gmail]/Drafts"
host = imaps://imap.gmail.com
user = user@gmail.com
pass = YX]8g76G_2^sFbd
port = 993
sslverify = false
IMAP sunucunuz SSL kullanmıyorsa, muhtemelen son iki satıra ihtiyacınız olmayacak ve host değeri imap://
yerine imaps://
olacaktır.
Bunu ayarladıktan sonra, git imap-send
komutunu kullanarak belirtilen IMAP sunucusunun Taslaklar klasörüne yama serisini yerleştirebilirsiniz:
$ cat *.patch |git imap-send
Resolving imap.gmail.com... ok
Connecting to [74.125.142.109]:993... ok
Logging in...
sending 2 messages
100% (2/2) done
Bu aşamada, Taslaklar klasörüne giderek, "Alıcı" alanını gönderdiğiniz yama serisinin e-posta listesine göre ayarlayabilir ve gerekirse proje yürütücüsünü veya ilgili kişiyi "CC" olarak ekleyebilirsiniz. Artık e-postanızı göndermeye hazırsınız.
Ayrıca yamaları bir SMTP sunucusu aracılığıyla da gönderebilirsiniz.
Aynı yukarıda olduğu gibi, her değeri ayrı ayrı git config
komutlarıyla ayarlayabilir veya ~/.gitconfig
dosyanızdaki "sendemail" bölümüne manuel olarak ekleyebilirsiniz:
[sendemail]
smtpencryption = tls
smtpserver = smtp.gmail.com
smtpuser = user@gmail.com
smtpserverport = 587
Bunu yaptıktan sonra, yamalarınızı göndermek için git send-email
komutunu kullanabilirsiniz:
$ git send-email *.patch
0001-added-limit-to-log-function.patch
0002-changed-log-output-to-30-from-25.patch
Who should the emails appear to be from? [Jessica Smith <jessica@example.com>]
Emails will be sent from: Jessica Smith <jessica@example.com>
Who should the emails be sent to? jessica@example.com
Message-ID to be used as In-Reply-To for the first email? y
Sonra, Git gönderdiğiniz her bir yaman için şöyle bir günlük bilgisi çıkarır:
(mbox) Adding cc: Jessica Smith <jessica@example.com> from
\line 'From: Jessica Smith <jessica@example.com>'
OK. Log says:
Sendmail: /usr/sbin/sendmail -i jessica@example.com
From: Jessica Smith <jessica@example.com>
To: jessica@example.com
Subject: [PATCH 1/2] added limit to log function
Date: Sat, 30 May 2009 13:29:15 -0700
Message-Id: <1243715356-61726-1-git-send-email-jessica@example.com>
X-Mailer: git-send-email 1.6.2.rc1.20.g8c5b.dirty
In-Reply-To: <y>
References: <y>
Result: OK
Özet
Bu bölüm, karşılaşabileceğiniz birkaç farklı Git projesi türüyle başa çıkmanın yaygın iş akışlarını anlattı ve bu süreci yönetmenize yardımcı olacak birkaç yeni aracı tanıttı. Şimdi, işin diğer yüzüyle nasıl çalışılacağını göreceksiniz: Bir Git projesini yürütmek. Bir hayırsever diktatör veya birleştirme yöneticisi olmayı öğreneceksiniz.