Projeye katkı sağlamanın yanı sıra genellikle bilmeniz gereken bir diğer beceri de Bir projeyi etkili bir şekilde yürütmektir.
Bu format-patch
ile oluşturulan ve size e-posta yoluyla gönderilen yamaları kabul etmek ve uygulamak veya eklediğiniz uzak dallardaki değişiklikleri projenize birleştirmekten oluşabilir.
İster klasik bir repoyu yürütüyor olun, ister yamaları doğrulayarak veya onaylayarak projeye yardımcı olun; diğer katkıda bulunanlar için en açık ve sizin için uzun vadede en sürdürülebilir kabul yöntemini bilmeniz gerekir.
Yeni bir çalışmayı birleştirmeyi düşündüğünüzde, sırf bunu denemek için geçici bir tematik dal oluşturmak iyi bir fikirdir.
Bu şekilde, bir yamanın detaylarını bireysel olarak ayarlamak ve işe yaramıyorsa daha sonra geri dönmek üzere bir kenara ayırmak için zamanınız olur.
Denemeyi yapacağınız işin konusuna dayanan basit ve açıklayıcı bir dal adı oluşturursanız (ör. ruby_client
vb); bir süre terk edip daha sonra geri dönmek zorunda kalırsanız, kolaylıkla hatırlayabilirsiniz.
Git projesinin yürütücüsü de genellikle bu dalları isimlendirir (ör. sc/ruby_client
. Surada sc
çalışmayı ekleyen kişinin kısaltmasıdır).
Hatırlayacağınız gibi, bunu master
dalınızdan şu şekilde oluşturabilirsiniz:
$ git branch sc/ruby_client master
Veya doğrudan o dala geçmek istiyorsanız, checkout -b
seçeneğini kullanabilirsiniz:
$ git checkout -b sc/ruby_client master
Şimdi aldığınız çalışmayı bu tematik dala eklemeye hazırsınız ve onu daha uzun vadeli dallarınıza birleştirip birleştirmeyeceğinize karar verebilirsiniz.
E-posta yoluyla alınan bir yamayı projenize birleştirmeniz gerekiyorsa, yamayı test etmek için tematik dalınıza uygulamanız gerekir.
E-postayla gönderilen bir yamayı uygulamanın iki yolu vardır: git apply
ve git am
.
Eğer birisi yamayı git diff
veya Unix’un diff
komutunun bir türevi ile oluşturduysa (ki bir sonraki bölümde göreceğiniz üzere bu önerilmez), yamayı git apply
komutu ile uygulayabilirsiniz.
Yamayı /tmp/patch-ruby-client.patch
dosyasına kaydettiğinizi farzedersek, şu şekilde uygulayabilirsiniz:
$ git apply /tmp/patch-ruby-client.patch
Bu, çalışma dizininizdeki dosyaları değiştirir.
Bir yama uygulamak için patch -p1
komutunu çalıştırmakla neredeyse aynıdır; ancak daha paranoiddir ve patch’e göre daha az belirsiz eşleşme (fuzzy match) kabul eder.
Ayrıca, git diff
formatında açıklanmış dosya ekleme, silme ve yeniden adlandırma işlemlerini, patch
'in yapmayacağı şekilde ele alır.
Son olarak, git apply
uygulamanızda "tümünü uygula" veya "hiçbirini uygulama" kararını vermeniz gereken bir modelidir: patch
ise yamaları kısmen uygulayabilir ve çalışma dizenizi tuhaf bir durumda bırakabilir.
git apply
genel olarak patch
'den çok daha katı davranır.
Size bir katkı kaydı oluşturmaz: çalıştırdıktan sonra, değişiklikleri elle aşamalandırmanız ve katkı işlemeniz gerekir.
git apply
komutunu, bir yamayı gerçekten uygulamadan önce, düzgün bir şekilde uygulanıp uygulanamayacağını kontrol etmek için de kullanabilirsiniz.
Bunun için git apply --check
komutu yamayla birlikte çalıştırabilirsiniz.
$ git apply --check 0001-seeing-if-this-helps-the-gem.patch
error: patch failed: ticgit.gemspec:1
error: ticgit.gemspec: patch does not apply
Eğer çıktı yoksa, yama temiz bir şekilde uygulanabilir demektir. Bu komut ayrıca, kontrolün başarısız olduğu durumlarda da sonucu sıfır olmayan bir durumla (non-zero status) çıkar, bu nedenle isterseniz bu komutu betiklerde de kullanabilirsiniz.
Eğer geliştirici yamasını oluşturmak için format-patch
komutunu kullanacak tecrübede bir Git kullanıcısıysa; yama yazar bilgisi ve bir katkı mesajı da içereceği için, işiniz daha kolay olur.
Mümkünse, geliştiricilerinizi yamalarını oluşturmak için diff
yerine format-patch
kullanmaları yönünde teşvik edin.
Yalnızca eski yamalar (legacy patch) ve benzeri durumlar için git apply
kullanmanız gerekir.
format-patch
ile oluşturulan bir yamayı uygulamak için git am
("bir posta kutusundan bir dizi yamayı uygulamak" için bu komut kullanıldığından am
olarak adlandırılır) kullanılır.
git am
komutu teknik olarak, bir veya daha fazla e-posta mesajını tek bir metin dosyasında depolamak için oluşturulan basit bir düz-metin biçimi olan "mbox" dosyasını okumak amacıyla oluşturulmuştur.
Ve şuna benzer:
From 330090432754092d704da8e76ca5c05c198e71a8 Mon Sep 17 00:00:00 2001
From: Jessica Smith <[email protected]>
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
Bu, önceki bölümde gördüğünüz git format-patch
komutunun çıktısının başlangıcıdır; aynı zamanda geçerli bir mbox e-posta biçimini temsil eder.
Eğer biri size yamayı git send-email
komutunu kullanarak düzgün şekilde e-posta ile gönderdiyse; ve siz de bunu mbox biçiminde indirir ve git am
'i o mbox dosyasına işaret edecek şekilde ayarlarsanız; gördüğü tüm yamaları uygulamaya başlayacaktır.
Eğer bir mbox formatında birkaç e-postayı kaydedebilen bir posta istemcisi çalıştırıyorsanız, tüm yama serilerini bir dosyaya kaydedip, bunların hepsini tek seferde uygulamak için git am
'i kullanabilirsiniz.
Ancak, birisi git format-patch
kullanarak oluşturulan bir yama dosyasını bir bilet sistemi veya benzer bir yere yüklediyse; bu dosyayı yerel olarak kaydedip, ardından diskte kaydedilen bu dosyayı uygulamak için git am
'e iletebilirsiniz:
$ git am 0001-limit-log-function.patch
Applying: add limit to log function
Gördüğünüz gibi, temiz bir şekilde uygulandı ve otomatik olarak yeni bir katkı oluşturuldu.
Yazar bilgileri, e-postanın From
(gönderici) ve Date
(tarih) başlıklarından; katkı mesajı, e-postanın Subject
(konu) ve yamadan önceki gövde kısmından alınır.
Örneğin, yukarıdaki mbox örneğinden uyarlanan bir yama için oluşturulan katkı şöyle görünecektir:
$ git log --pretty=fuller -1
commit 6c5e70b984a60b3cecd395edd5b48a7575bf58e0
Author: Jessica Smith <[email protected]>
AuthorDate: Sun Apr 6 10:17:23 2008 -0700
Commit: Scott Chacon <[email protected]>
CommitDate: Thu Apr 9 09:19:06 2009 -0700
add limit to log function
Limit log functionality to the first 20
Commit
(katkı) bilgileri yamayı uygulayan kişiyi ve uygulanma zamanını gösterir.
Author
(yazar) bilgileri ise özgün yamayı oluşturan kişiyi ve ne zaman oluşturduğunu gösterir.
Ama yamanın temiz bir şekilde uygulanamaması ihtimal dahilindedir.
Belki ana dalınız, yamanın oluşturulduğu daldan çok uzaklaşmıştır veya yama henüz uygulamadığınız başka bir yamaya bağlıdır.
Bu durumda, git am
işlemi başarısız olacak ve ne yapmak istediğinizi size soracaktır:
$ git am 0001-seeing-if-this-helps-the-gem.patch
Applying: seeing if this helps the gem
error: patch failed: ticgit.gemspec:1
error: ticgit.gemspec: patch does not apply
Patch failed at 0001.
When you have resolved this problem run "git am --resolved".
If you would prefer to skip this patch, instead run "git am --skip".
To restore the original branch and stop patching run "git am --abort".
Bu komut, sorun yaşadığı dosyalara "çatışan birleştirme" veya "yeniden temelleme işlemi" gibi çatışma işaretçileri koyar.
Bu sorunu çözmenin yolu neredeyse aynıdır: dosyayı çatışmayı çözecek şekilde düzenleyin, yeni dosyayı hazırlayın ve ardından bir sonraki yamaya devam etmek için git am --resolved
komutunu çalıştırın:
$ (fix the file)
$ git add ticgit.gemspec
$ git am --resolved
Applying: seeing if this helps the gem
Eğer Git’in çatışmayı biraz daha akıllıca çözmesini istiyorsanız -3
seçeneğini kullanarak, Git’in üç yollu bir birleştirme yapmayı denemesini sağlarsınız.
Yama üzerindeki işlenecek olan katkı, sizin reposunuzda bulunmuyorsa çalışmayacağı için, bu seçenek varsayılan olarak etkinleştirilmemiştir.
Eğer o katkı sizin reposunuzda mevcutsa (eğer yama bir halka açık katkıya dayanıyorsa), o zaman -3
seçeneği genellikle bir çatışmalı yamanın uygulanması konusunda daha akıllıdır:
$ git am -3 0001-seeing-if-this-helps-the-gem.patch
Applying: seeing if this helps the gem
error: patch failed: ticgit.gemspec:1
error: ticgit.gemspec: patch does not apply
Using index info to reconstruct a base tree...
Falling back to patching base and 3-way merge...
No changes -- Patch already applied.
Yukarıdaki durumda -3
seçeneği olmasaydı, yama bir çatışma olarak kabul edilirdi.
-3
seçeneği kullanıldığı için temiz bir şekilde uygulandı.
Eğer bir mbox’tan bir dizi yama uyguluyorsanız; her bulduğu yamada durup, onu uygulamak isteyip istemediğinizi soran, etkileşimli am
komutunu da çalıştırabilirsiniz:
$ git am -3 -i mbox
Commit Body is:
--------------------------
seeing if this helps the gem
--------------------------
Apply? [y]es/[n]o/[e]dit/[v]iew patch/[a]ccept all
Eğer kaydedilmiş birkaç yamanız varsa ve hangilerini zaten uyguladığınızı veya uygulayacağınızı hatırlayamıyorsanız; öncesinde yamayı görmenize olanak sağladığı için, bu özellik oldukça kullanışlıdır.
Bir tema için tüm yamalar uygulandığında ve dalınıza katkı olarak işlendiğinde, bunları uzun vadeli çalışan bir dala birleştirip birleştirmeyeceğinizi veya nasıl birleştireceğinizi seçebilirsiniz.
Eğer bu katkı; kendi reposunu kuran, bir dizi değişiklik yapıp, buraya iten ve ardından değişikliklerin URL’sini ve değişikliklerin bulunduğu uzak dalın adını size gönderen bir Git kullanıcısından geldiyse, onları bir uzak repo olarak ekleyebilir ve yerel olarak birleştirebilirsiniz.
Örneğin, Jessica size kendi reposunun ruby-client
dalında harika bir yeni özellik olduğunu söyleyen bir e-posta gönderirse; onun uzak reposunu ekleyip, bu yerelde dala geçiş yaparak, bu özelliği test edebilirsiniz:
$ git remote add jessica git://github.com/jessica/myproject.git
$ git fetch jessica
$ git checkout -b rubyclient jessica/ruby-client
Daha sonra, size başka bir harika özelliğe sahip başka bir dalı içeren yeni bir e-posta gönderirse, zaten uzak sunucuyu kurduğunuz için doğrudan fetch
ve checkout
yapabilirsiniz.
Biriyle sürekli birlikte çalışıyorsanız en kullanışlı olan yöntem budur. Eğer birisi arada bir ve sadece tek bir yama eklemek istiyorsa, o zaman bu değişiklikleri e-posta yoluyla kabul etmek, herkesin kendi sunucusunu çalıştırmasından ve birkaç yama almak için sürekli olarak uzak sunucular ekleyip, kaldırmasından daha tasarruflu bir zaman yönetimidir. Ayrıca, muhtemelen yalnızca bir veya iki yama sağlayan herkes için yüzlerce uzak sunucu eklemek istemezsiniz. Her ne kadar, betikler ve barındırılan hizmetler bu işi kolaylaştırabilse de, bu büyük ölçüde sizin ve katkı sağlayan geliştiricilerin nasıl geliştirme yaptığına bağlıdır.
Bu yaklaşımın bir diğer avantajı ise geçmişini de almanızdır.
Geçerli birleştirme sorunlarına sahip olabilseniz dahi, bu çalışmalarının geçmişinizde nerede olduğunu bilirsiniz.
Varsayılan olarak sağlanan düzgün bir üç yollu birleştirme, -3
sağlamak zorunda kalmaktan ve yamanın erişiminiz olan herkese açık bir katkıya dayanmasını ummaktan iyidir.
Eğer sürekli olarak bir kişiyle çalışmıyor ama yine de yamayı onlardan bu şekilde çekmek istiyorsanız, git pull
komutuna uzak repo URL’sini girebilirsiniz.
Bu, tek seferlik bir çekme işlemi yapar ama URL’yi uzak bir referans olarak kaydetmez:
$ git pull https://github.com/onetimeguy/project
From https://github.com/onetimeguy/project
* branch HEAD -> FETCH_HEAD
Merge made by the 'recursive' strategy.
Şimdi, üzerinde katkı yapılan bir tematik dalınız var. Bu noktada, onunla ne yapmak istediğinizi belirleyebilirsiniz. Bu bölümde, ana dalınıza bir yamayı birleştirdiğinizde, tam olarak neyi tanıtacağınızı incelemek için birkaç komutu tekrar ele alacağız.
Tematik dalda olan, ancak ana dalınızda olmayan tüm katkıların gözden geçirilmesinde fayda vardır.
Ana dalınızda bulunan katkıları bundan hariç tutmak için --not
seçeneğini dal adının önüne ekleyebilirsiniz.
Bu, daha önce kullandığımız master..contrib
biçimiyle aynı işlemi yapar.
Örneğin, katkılayıcınız size iki yama gönderirse ve siz contrib
adında bir dal oluşturup bunları oraya uygularsanız, şunu çalıştırabilirsiniz:
$ git log contrib --not master
commit 5b6235bd297351589efc4d73316f0a68d484f118
Author: Scott Chacon <[email protected]>
Date: Fri Oct 24 09:53:59 2008 -0700
seeing if this helps the gem
commit 7482e0d16d04bea79d0dba8988cc78df655f16a0
Author: Scott Chacon <[email protected]>
Date: Mon Oct 22 19:38:36 2008 -0700
updated the gemspec to hopefully work better
Hatırlayacağınız üzere her katkının hangi değişiklikleri içerdiğini görmek için, git log
komutuna -p
seçeneğini ekleyebilirsiniz. Ayrıca her katkıyla gelen fark da gösterilecektir.
Ana dal ve tematik dalı birleştirirseniz kodda ne gibi farklılıklar olacağının tam bir resmini görmek isterseniz, doğru sonuçları elde etmek için garip bir hile kullanmanız gerekebilir. Şunu çalıştırmayı düşünebilirsiniz:
$ git diff master
Bu komut size bir fark gösterir, ancak sonuç yanıltıcı olabilir.
Eğer master
dalınız, tematik dalınızı oluşturduğunuzdan bu yana ilerlemişse, çok garip sonuçlar elde edebilirsiniz.
Bunun sebebi, Git’in üzerinde bulunduğunuz tema dalındaki son katkının pozuyla, master
dalındaki son katkının pozunu doğrudan karşılaştırmasıdır.
Örneğin, master
dalındaki bir dosyaya bir satır eklerseniz; pozların doğrudan karşılaştırılması, tematik dalın bu satırı kaldıracakmış gibi görünmesine neden olur.
Eğer master
dalı tematik dalınızın doğrudan bir atası ise, bu bir sorun değildir; ancak eğer iki geçmiş ayrıldıysa, fark master
dalına özgü olan her şeyi kaldırıyor ve tema dalınızdaki tüm yeni şeyleri ekliyormuş gibi görünecektir.
Gerçekte görmek istediğiniz şey, konu dalına eklenen değişikliklerdir, yani bu dalı ana dala birleştirdiğinizde getireceğiniz çalışma. Bunu görmek için, Git’in tema dalınızın son katkısını, master üzerindeki ilk ortak atasıyla karşılaştırması neticesinde görebilirsiniz.
Teknik olarak bunu yapmanın yolu: ortak atayı açıkça bulup ardından diff’i üzerinde çalıştırmaktır:
$ git merge-base contrib master
36c7dba2c95e6bbb78dfa822519ecfec6e1ca649
$ git diff 36c7db
or, more concisely:
$ git diff $(git merge-base contrib master)
Yine de bunlar özellikle kullanışlı yöntemler değil, bu yüzden Git aynı işi yapmak için başka bir kısaltma sağlar: üç nokta sözdizimi.
git diff
komutu bağlamında: diff
yapmak için üzerinde bulunduğunuz dalın son katkısı ile başka bir dalın son ortak atası arasına üç nokta (…) koyabilirsiniz:
$ git diff master...contrib
Bu komut, mevcut tema dalınızın, master ile ortak atasından bu yana getirdiği çalışmayı gösterir. Bu akılda tutmaya değer ve çok kullanışlı bir sözdizimidir.
Tema dalınızdaki tüm çalışma, ana dala daha yakın bir dala birleştirilmeye hazır olduğunda, sıradaki soru bunun nasıl yapılacağıdır. Bunun da ötesinde, projenizi yürütmek için hangi genel iş akışını kullanmak istiyorsunuz? Şimdi elinizdeki pek çok seçenekten birkaçını ele alacağız.
En temel iş akışı, tüm çalışmayı doğrudan master
dalınıza birleştirmektir.
Bu senaryoda, kararlı kodu içeren bir master
dalınız bulunmaktadır.
Tematik dalda tamamlandığını düşündüğünüz veya bir başkasının katkıda bulunduğu ama sizin onayladığınız bir çalışma varsa, bunu ana dalınıza birleştirir ve artık ihtiyaç duymadığınız tema dalını silersiniz. Bu süreci her defasında tekrar edersiniz.
Örneğin, ruby_client
ve php_client
adlı iki dalında çalışma yapılan Bir kaç tematik dallı bir geçmiş. gibi bir repomuz olduğunu varsayalım.
Eğer, önce ruby_client
ve ardından da php_client
dalını birleştirirsek, geçmişiniz Bir tema dalını birleştirdikten sonrası. gibi görünecektir.
Bu muhtemelen en basit iş akışıdır; ancak neyi değiştirdiğinize çok dikkat ettiğiniz, daha büyük ve istikrarlı projelerle uğraşıyorsanız, sorun yaşayabilirsiniz.
Daha önemli bir projeniz varsa, iki aşamalı bir birleştirme döngüsü kullanmak isteyebilirsiniz.
Bu senaryoda, sadece çok kararlı bir sürüm çıktığında güncellenecek olan master
ve her yeni kodunuzu üzerinde geliştirip denediğiniz develop
adında, iki adet uzun ömürlü dalınız var:
Her iki dalı da düzenli olarak açık reponuza (public repository) itiyorsunuz.
Birleştirilecek yeni bir tema dalınız olduğunda (Tema dalı birleşmesi öncesi.), bunu develop
dalına birleştirirsiniz (Tema dalı birleşmesi sonrası.); ardından, yeni bir sürüm etiketlediğinizde, master
dalını ileri sararak (fast-forward) şu anda istikrarlı olan develop
dalını bulunduğu yere getirirsiniz (Yeni sürüm sonrası.).
Bu şekilde, insanlar reponuzu kopyaladığında; ya en son "kararlı" sürümü derlemek ve bunu kolayca güncellemek için master
dalına geçebilir ya da daha en "güncel" içeriği içeren develop
dalına.
Ayrıca, tüm çalışmaların birleştirildiği bir integrate
dalı oluşturarak bu anlayışı genişletebilirsiniz.
Bu dal üzerindeki kod tabanı kararlı hale gelip, testleri geçtiğinde, bunu bir develop
dalına birleştirebilirsiniz; ve burada kararlı durumu kanıtlandığında, master
dalınızı bu noktaya doğru ileri sararsınız.
Bu Git projesinde dört uzun ömürlü dal bulunmaktadır: master
, next
, yeni güncellemeler için pu
(proposed updates) ve bakım geri portları için maint
(maintenance).
Yeni çalışma görücüye çıktığında, bunlar daha önce anlatılana benzer şekilde (bkz Çoklu paralel tema dallarının karmaşıklığını yönetmek.) yürütücünün reposundaki tema dallarına toplanır (bkz. Çoklu paralel tema dallarının karmaşıklığını yönetmek.).
Bu noktada, çalışmalar, "güvenilir ve canlıya çıkmaya hazır mı, yoksa üzerinde biraz daha çalışılması mı gerekiyor" kararı verilmek üzere değerlendirilirler.
Güvenilir olanlar next
dalına birleştirilir ve bu dal herkesin deneyebilmesi için yukarı itilir.
Eğer konular halen geliştirilmeye ihtiyaç duyuyorsa, bunlar next
yerine pu
dalına birleştirilir.
Tamamen istikrarlı oldukları belirlendiğinde, yeniden master
dalına birleştirilirler.
next
ve pu
dalları daha sonra master
dalından yeniden inşa edilir.
Bu, master
dalının neredeyse her zaman ileri gitmesi, next
dalının zaman zaman yeniden temellenmesi (rebase) ve pu
dalının daha da sık yeniden temellenmesi, anlamına gelir:
Bir tema dalı nihayet master
dalına birleştirildiğinde, artık repodan kaldırılır.
Git projesinin ayrıca son sürümden çatallanmış maint
adlı bir bakım dalı vardır.
Bu dal, bir bakım sürümü gerektiğinde geriye dönük yamalar sağlamak için kullanılır.
Bu sistemde, yürütücünün yeni katkıları değerlendirmesine yardımcı olmak için yapılandırılmış özelleştirilmiş bir iş akışı vardır. Git reposunu kopyaladığınızda, projeye nasıl katkıda bulunmak istediğinize veya geliştirme döngüsünde ne kadar ilerlemek istediğinize bağlı olarak; projenin farklı gelişim aşamalarını gözlemlemek amacıyla geçiş yapabileceğiniz, dört farklı dalınız olur. Bu iş akışını daha iyi anlamak için Git Yürütücü Kılavuzu'nu inceleyebilirsiniz.
Diğer yürütücüler, doğrusal bir geçmişe sahip olmak için genellikle için katkılanan çalışmaları master dalının üstüne yeniden temellemeyi (rebase) veya ayıklamayı tercih ederler.
Bir tema dalında birleştirmek istediğiniz bir çalışmanız varsa, o dala geçer ve değişiklikleri mevcut master
(veya develop
, vb.) dalı üstüne yeniden inşa etmek için temelleme (rebase) komutunu çalıştırırsınız.
Bu işlem sorunsuz tamamlanırsa, master
dalınızı ileri sarabilir ve sonuçta doğrusal bir proje geçmişine sahip olursunuz.
Tanıtılan bir çalışmayı bir daldan başka bir dala taşımanın bir diğer yolu da onu ayıklamaktır. Git’te ayıklama işlemi, bir tek katkı için bir yeniden temelleme gibidir. Bir katkıyla yapılan değişiklikleri alır ve bunları şu anda bulunduğunuz dala tekrar uygulamaya çalışır. Bir tema dalında birkaç katkımız varsa ve bunları ayıklayıp yalnızca birini almak istiyorsanız veya bir tema dalında yalnızca bir katkınız varsa ve yeniden temellemek yerine bunu tercih etmek istiyorsanız, bu özellik kullanışlıdır. Örneğin, şöyle bir projeniz olduğunu varsayalım:
Eğer e43a6
katkısını ana dalınıza çekmek istiyorsanız, şunu çalıştırabilirsiniz:
$ git cherry-pick e43a6
Finished one cherry-pick.
[master]: created a0a41a9: "More friendly message when locking the index fails."
3 files changed, 17 insertions(+), 3 deletions(-)
Bu, e43a6
ile tanıtılan değişikliği çeker, ancak uygulanan tarihi farklı olduğu için yeni bir katkı SHA-1 değeri alırsınız.
Artık geçmişiniz şöyle görünür:
Şimdi tema dalınızı kaldırabilir ve içe almak istemediğiniz katkıları atabilirsiniz.
Eğer çok sayıda birleştirme ve yeniden temelleme yapıyorsanız veya uzun ömürlü bir tema dalını sürdürüyorsanız; Git’in rerere
olarak adlandırılan yardımcı bir özelliği vardır.
Rerere, "reuse recorded resolution" (kaydedilmiş çözümü yeniden kullan) anlamına gelir ve çakışmaları manuel olarak çözmeniz gerektiğinde kullanabileceğiniz kestirme bir yoldur. Rerere etkinleştirildiğinde, Git başarılı birleştirmelerin öncel ve ardıl pozlar kümesini saklar; ve eğer daha önce düzelttiğiniz bir çakışma ile tam olarak aynı görünen yeni bir çakışma fark ederse, sizi bununla meşgul etmeden, daha önceki çözümü kullanır.
Bu özellik iki kısımdan oluşur: bir yapılandırma ayarı ve bir komut.
Yapılandırma ayarı rerere.enabled
şeklindedir ve genel yapılandırmanıza eklemek oldukça kullanışlıdır:
$ git config --global rerere.enabled true
Böylece, çakışmaları çözen bir birleştirme yaptığınızda, bu çözüm gelecekte ihtiyaç duymanız ihtimaline binaen önbelleğe kaydedilecektir.
İhtiyacınız olduğunda, git rerere
komutunu kullanarak rerere önbelleğiyle etkileşime geçebilirsiniz.
Tek başına çağrıldığında; Git, çözümler veritabanını kontrol ederek, mevcut birleştirme çatışmasıyla bir eşleşme bulmaya ve bunu çözmeye çalışır (rerere.enabled
yapılandırması true
olarak ayarlandıysa, bu işlem otomatik olarak yapılır).
Kaydedilecek ögeleri görmek, önbellekten belirli bir çözümü silmek veya tüm önbelleği temizlemek için kullanılabilecek, alt komutlar da vardır.
rerere
komutunu ch07-git-tools.asc bölümünde daha detaylı olarak ele alacağız.
Bir sürüm yayımlamaya karar verdiğinizde, bu sürümü gelecekte yeniden oluşturabilmek için etiketlemek isteyebilirsiniz. Yeni bir etiketi ch02-git-basics.asc bölümünde anlatıldığı gibi oluşturabilirsiniz. Eğer etiketi yürütücü olarak imzalamaya karar verirseniz, etiketleme işlemi şöyle görünebilir:
$ git tag -s v1.5 -m 'my signed 1.5 tag'
You need a passphrase to unlock the secret key for
user: "Scott Chacon <[email protected]>"
1024-bit DSA key, ID F721C45A, created 2009-02-09
Etiketlerinizi imzalarsanız, etiketlerinizi imzalamak için kullandığınız genel PGP anahtarını dağıtma sorunuyla karşılaşabilirsiniz.
Git proje yürütücüsü, genel anahtarlarını repoya bir blob olarak dahil edip, ardından doğrudan bu içeriğe işaret eden bir etiket ekleyerek bu sorunu çözmüştür.
Bunu yapmak için, gpg --list-keys
komutunu çalıştırarak hangi anahtarı kullanmak istediğinizi belirleyebilirsiniz:
$ gpg --list-keys
/Users/schacon/.gnupg/pubring.gpg
---------------------------------
pub 1024D/F721C45A 2009-02-09 [expires: 2010-02-09]
uid Scott Chacon <[email protected]>
sub 2048g/45D02282 2009-02-09 [expires: 2010-02-09]
Daha sonra, anahtarı dışa aktarıp, bu içeriği git hash-object
üzerinden yönlendirerek, anahtarı doğrudan Git veritabanına aktarabilirsiniz.
Bu şekilde Git, bu içeriğe sahip yeni bir blob oluşturur ve blob’un SHA-1 değerini size geri verir:
$ gpg -a --export F721C45A | git hash-object -w --stdin
659ef797d181633c87ec71ac3f9ba29fe5775b92
Artık anahtar içeriğiniz Git’te olduğuna göre, hash-object
komutunun size verdiği yeni SHA-1 değerini belirterek doğrudan ona işaret eden bir etiket oluşturabilirsiniz:
$ git tag -a maintainer-pgp-pub 659ef797d181633c87ec71ac3f9ba29fe5775b92
git push --tags
komutunu çalıştırırsanız, maintainer-pgp-pub
etiketi herkesle paylaşılacaktır.
Bir etiketi doğrulamak isteyen biri; PGP anahtarınızı doğrudan içe aktarmak için, blob’u veritabanından çekip, GPG’ye aktarabilir:
$ git show maintainer-pgp-pub | gpg --import
Bu anahtar, imzalı tüm etiketlerinizi doğrulamak için kullanabilir.
Ayrıca, etiket mesajında talimatlar eklerseniz; git show <etiket>
komutuyla son kullanıcıya etiket doğrulaması hakkında daha belirli yönergeler verebilirsiniz.
Git’in her katkıyla tekdüze olarak artan, 'v123' gibi numaraları veya benzer bir şeyi olmadığından; bir katkıyı insanlar tarafından okunabilir bir isimle eşleştirmek için, o katkı üzerinde git describe
komutunu çalıştırabilirsiniz.
Bunun sonucunda, Git; o katkıdan önceki en son etiketin adını, arkasından bu etiketten bu katkıya kadar işlenen katkı sayısını ve en arkaya da tanımlanan katkının kısmi SHA-1 değerini içeren bir dize oluşturur (en başa Git’i simgeleyen "g" harfi eklenir):
$ git describe master
v1.6.2-rc1-20-g8c5b85c
Bu şekilde, bir poz veya derleme oluşturup okunaklı bir isim verebilirsiniz.
Aslında, eğer Git’i kendi reposundan kopyaladığınız kaynak kodundan derlemişseniz, git --version
komutu size şuna benzeyen bir çıktı verir.
Eğer doğrudan etiketlediğiniz bir katkıyı tanımlıyorsanız, size sadece etiket adını verir.
git describe
komutu, varsayılan olarak, (-a
veya -s
bayrağı ile oluşturulan) dipnotlu etiketlere ihtiyaç duyar. Eğer hafif (dipnotsuz) etiketlerden de faydalanmak istiyorsanız, komuta --tags
seçeneğini ekleyin.
Bu dizeyi git checkout
veya git show
komutunun hedefi olarak da kullanabilirsiniz, ancak sonundaki kısaltılmış SHA-1 değerine dayansa da sonsuza kadar geçerli olmayabilir.
Örneğin, Linux çekirdeği son zamanlarda SHA-1 nesne benzersizliğini sağlamak için 8’den 10 karaktere geçti, bu nedenle eski git describe
çıktı adları geçersiz hale geldi.
Diyelimk ki şimdi bir sürüm yayımlamak istiyorsunuz.
Bunun için yapmanız gerekenlerden biri, Git’i kullanmayan garibanlar için kodunuzun en son pozunun bir arşivini oluşturmaktır.
Bunun için git archive
komutunu kullanmalısınız:
$ git archive master --prefix='project/' | gzip > `git describe master`.tar.gz
$ ls *.tar.gz
v1.6.2-rc1-20-g8c5b85c.tar.gz
Eğer birisi bu sıkıştırılmış tar dosyasını açarsa, projenizin en son pozunu bir proje dizini altına almış olur.
Aynı şekilde bir zip arşivi de oluşturabilirsiniz, ancak bunu git archive
komutuna --format=zip
seçeneğini bağlayarak yapabilirsiniz:
$ git archive master --prefix='project/' --format=zip > `git describe master`.zip
Artık projenizin sürümünün, web sitenize yükleyebileceğiniz veya birilerine e-posta ile gönderebileceğiniz, güzel bir tar dosyası ve zip arşivi vardır.
Artık, projenizdeki son değişiklikler hakkında bilgi sahibi olmak isteyenlere bir e-posta gönderme zamanı geldi.
Son sürüm veya e-postanızdan bu yana projenizde yapılan değişiklikleri tutan değişim günlüğünü hızlıca elde etmek için git shortlog
komutunu kullanabilirsiniz.
Bu komut, veerdiğiniz aralıktaki tüm katkıları özetler.
Örneğin, son sürümünüz v1.0.1 ise, aşağıdaki komut size son sürümünüzden bu yana yapılan tüm katkıların bir özetini verir:
$ git shortlog --no-merges master --not v1.0.1
Chris Wanstrath (6):
Add support for annotated tags to Grit::Tag
Add packed-refs annotated tag support.
Add Grit::Commit#to_patch
Update version and History.txt
Remove stray `puts`
Make ls_tree ignore nils
Tom Preston-Werner (4):
fix dates in history
dynamic version method
Version bump to 1.0.2
Regenerated gemspec for version 1.0.2
v1.0.1’den bu yana yapılan tüm katkıların yazarlarına göre gruplandırılmış temiz bir özet elde eder ve ardından bu özeti listenize e-posta olarak gönderebilirsiniz.