Git
Chapters ▾ 2nd Edition

7.1 Git Tools - Düzeltme Seçimi

By now, you’ve learned most of the day-to-day commands and workflows that you need to manage or maintain a Git repository for your source code control. You’ve accomplished the basic tasks of tracking and committing files, and you’ve harnessed the power of the staging area and lightweight topic branching and merging.

Now you’ll explore a number of very powerful things that Git can do that you may not necessarily use on a day-to-day basis but that you may need at some point.

Düzeltme Seçimi

Git, bir veya birkaç katkı veya katkı aralığına birkaç şekilde atıfta bulunmanızı sağlar. Bunlar her zaman açık olmayabilir, ancak bilmeniz faydalı olabilir.

Tekli Düzeltmeler

Herhangi tek bir katkıyı 40 karakterlik tam bir SHA-1 karmasıyla (hash) gösterebilirsiniz, ancak katkıları daha insan dostu yollarla da belirtebilirsiniz. Bu bölüm, herhangi bir katkıyı belirtmek için kullanabileceğiniz çeşitli yolları açıklar.

Kısa SHA-1

Bir katkıyı belirtmek için SHA-1 karmasının ilk birkaç karakterini yazarsanız, yazdığınız karma en az dört karakter uzunluğunda ve belirsiz olmadığı sürece, Git hangi katkıya atıfta bulunduğunuzu anlayacak kadar akıllıdır. Başka bir deyişle, nesne veritabanında aynı önek ile başlayan başka bir nesne olmadığı müddetçe sorun yaşamazsınız.

Örneğin, belirli bir işlev eklediğinizi bildiğiniz bir katkıyı incelemek için, ilk önce git log komutunu çalıştırarak o katkıyı bulabilirsiniz:

$ git log
commit 734713bc047d87bf7eac9674765ae793478c50d3
Author: Scott Chacon <schacon@gmail.com>
Date:   Fri Jan 2 18:32:33 2009 -0800

    fixed refs handling, added gc auto, updated tests

commit d921970aadf03b3cf0e71becdaab3147ba71cdef
Merge: 1c002dd... 35cfb2b...
Author: Scott Chacon <schacon@gmail.com>
Date:   Thu Dec 11 15:08:43 2008 -0800

    Merge commit 'phedders/rdocs'

commit 1c002dd4b536e7479fe34593e72e6c6c1819e53b
Author: Scott Chacon <schacon@gmail.com>
Date:   Thu Dec 11 14:58:32 2008 -0800

    added some blame and merge stuff

Diyelim ki, SHA-1 özetinin 1c002dd... ile başladığı bir katkıyla ilgileniyorsunuz. Bu katkıyı incelemek için aşağıdaki git show çeşitlemelerinden herhangi birini kullanabilirsiniz (kısa versiyonların belirsiz olmadığı varsayılmaktadır):

$ git show 1c002dd4b536e7479fe34593e72e6c6c1819e53b
$ git show 1c002dd4b536e7479f
$ git show 1c002d

Git, SHA-1 değerleriniz için kısa, benzersiz bir kısaltma bulabilir. git log komutuna --abbrev-commit seçeneğini eklerseniz, çıktı daha kısa değerler kullanacak ancak bunları benzersiz tutacaktır; SHA-1’in belirsiz olmaması (benzersiz olması) için, varsayılan olarak yedi karakter kullanır ancak bu onu daha uzun hale getirir:

$ git log --abbrev-commit --pretty=oneline
ca82a6d changed the version number
085bb3b removed unnecessary test code
a11bef0 first commit

Genellikle, bir projenin içinde benzersiz olması için sekiz ila on karakter yeterlidir. Örneğin, - Şubat 2019 itibarıyla 875.000’den fazla katkı ve neredeyse yedi milyon nesne içeren - oldukça büyük bir proje olan Linux çekirdeğinde, SHA-1’leri ilk 12 karakteri aynı olan hiçbir nesne bulunmuyor.

Örnek 12. SHA-1 HAKKINDA KISA BİR NOT

Birçok insan, rastgele bir olay sonucu, repolarında birbirinden farklı iki nesnenin aynı SHA-1 değerine sahip olabileceğinden endişelenir. Peki sonra ne olur?

Eğer repoya daha önceden işlenmiş farklı bir nesnenin SHA-1 değerine sahip yeni bir nesne eklerseniz, Git önceki nesneyi zaten Git veritabanınızda görecek, bu nesnenin zaten yazıldığını varsayacak ve onu yeniden kullanacaktır. Bir noktada o nesneye geçmeye çalışırsanız, her zaman ilk nesnenin verisini alacaksınız.

Ancak, bu senaryonun gerçekleşme ihtimalinin, imkansıza yakın derecede olanaksız olduğunun farkında olmalısınız. SHA-1 özeti 20 bayt veya 160 bit’tir. Bu eşleşme olasılığının %50 olması için gerekli rastgele özetlenmiş nesne sayısı yaklaşık 2^80 (2 üzeri 80) civarındadır (çarpışma olasılığını belirleme formülü p = (n(n-1)/2) * (1/2^160)). 2 üzeri 80 yaklaşık olarak 1,2 x 10^24 veya kelimelere dökersek "milyon kere milyar kere milyar"dır. Bu da dünyadaki kum tanelerinin toplam sayısının yaklaşık 1,200 katıdır.

İşte bir SHA-1 çarpışmasını elde etmek için gerekenleri anlamanıza yardımcı olacak bir başka örnek: Dünyadaki 6,5 milyar insanın hepsi programlama yapıyor olsaydı ve bunların her biri, Linux çekirdeğine saniyede bir katkı işleyip (saniyede 6,5 milyon Git nesnesi) bunları devasa bir Git reposuna itseydi; bu repoda bir tek SHA-1 nesnesinin çarpışma olasılığının %50 olması, yaklaşık 2 yıl sürerdi. Bu nedenle, bir SHA-1 çarpışmasının gerçekleşme ihtimali, programlama ekibinizin tüm üyelerinin, aynı gece, farklı yerlerde, farklı şeylerle ilgilenirken, aniden kurtlar tarafından saldırıya uğraması ve öldürülmesinden daha düşüktür.

Dal Referansları

Belirli bir katkıya başvurmanın basit bir yolu, o dalın uç noktasındaki bir katkı olduğunda; bu durumda, bir katkı başvurusunu bekleyen herhangi bir Git komutunda sadece dal adını kullanabilirsiniz. Örneğin, bir daldaki son katkı nesnesini incelemek istiyorsanız, topic1 dalının ca82a6d... katkısına işaret ettiğini varsayarsak, aşağıdaki komutlar eşdeğerdir:

$ git show ca82a6dff817ec66f44342007202690a93763949
$ git show topic1

Bir dalın hangi SHA-1’e işaret ettiğini görmek istiyorsanız veya bu örneklerden herhangi birinin SHA-1’ler açısından neye denk geldiğini görmek istiyorsanız, rev-parse adlı bir Git aracını kullanabilirsiniz. Daha fazla bilgi için Git Internals adresine bakabilirsiniz; temelde, rev-parse daha düşük düzeyli işlemler için var ve günlük işlemlerde kullanılmak üzere tasarlanmamıştır. Ancak, bazen gerçekte ne olduğunu görmek gerektiğinde yardımcı olabilir. Burada dalınız üzerinde rev-parse çalıştırabilirsiniz.

$ git rev-parse topic1
ca82a6dff817ec66f44342007202690a93763949

Referans Günlüğü (Reflog) Kısa Adları

Git’in arka planda çalışırken yaptığı şeylerden biri, "reflog" olarak adlandırılan, HEAD ve dal referanslarınızın son birkaç ay boyunca nerede olduğunu kaydettiği bir günlük tutmaktır.

Referans günlügünüzü git reflog komutunu kullanarak görebilirsiniz:

$ git reflog
734713b HEAD@{0}: commit: fixed refs handling, added gc auto, updated
d921970 HEAD@{1}: merge phedders/rdocs: Merge made by the 'recursive' strategy.
1c002dd HEAD@{2}: commit: added some blame and merge stuff
1c36188 HEAD@{3}: rebase -i (squash): updating HEAD
95df984 HEAD@{4}: commit: # This is a combination of two commits.
1c36188 HEAD@{5}: rebase -i (squash): updating HEAD
7e05da5 HEAD@{6}: rebase -i (pick): updating HEAD

Herhangi bir nedenle dal ucu güncellendiğinde, Git bu bilgiyi geçici bir geçmişte sizin için saklar. Reflog verilerinizi eski katkılara başvurmak için de kullanabilirsiniz. Örneğin, repo ucunuzun beş önceki değerini görmek istiyorsanız, reflog çıktısında gördüğünüz @{5} referansını kullanabilirsiniz:

$ git show HEAD@{5}

Bu sözdizimini ayrıca bir dalın belirli bir süre önce nerede olduğunu görmek için de kullanabilirsiniz. Örneğin, master dalınızın dün nerede olduğunu görmek için şunu yazabilirsiniz:

$ git show master@{yesterday}

Bu, master dalınızın ucunun dün nerede olduğunu gösterir. Bu teknik, hala referans günlüğünüzde olan veriler için çalışır, bu nedenle birkaç aydan daha eski katkıları aramak için kullanamazsınız.

git log çıktısı gibi biçimlendirilmiş referans günlüğü bilgilerini görmek için git log -g komutunu çalıştırabilirsiniz:

$ git log -g master
commit 734713bc047d87bf7eac9674765ae793478c50d3
Reflog: master@{0} (Scott Chacon <schacon@gmail.com>)
Reflog message: commit: fixed refs handling, added gc auto, updated
Author: Scott Chacon <schacon@gmail.com>
Date:   Fri Jan 2 18:32:33 2009 -0800

    fixed refs handling, added gc auto, updated tests

commit d921970aadf03b3cf0e71becdaab3147ba71cdef
Reflog: master@{1} (Scott Chacon <schacon@gmail.com>)
Reflog message: merge phedders/rdocs: Merge made by recursive.
Author: Scott Chacon <schacon@gmail.com>
Date:   Thu Dec 11 15:08:43 2008 -0800

    Merge commit 'phedders/rdocs'

Reflog bilgilerinin kesinlikle yerel olduğunu bilmelisinizi - yalnızca sizin kendi reponuzda yaptığınız işlemlerin günlüğüdür. Referanslar, başkasının repo kopyasında aynı olmayacaktır; ayrıca bir repoyu başlangıçta klonladıktan hemen sonra, henüz repoda herhangi bir etkinlik olmadığından boş bir referans günlüğünüz olacaktır. git show HEAD@{2.months.ago} komutunu çalıştırmak; eğer projeyi en az iki ay önce kopyaladıysanız, yalnızca eşleşen katkıyı gösterecektir; eğer bundan daha yeni bir tarihte kopyaladıysanız, yalnızca ilk yerel katkınızı göreceksiniz.

Örnek 13. Reflog’u Git’in kabuk (shell) geçmişi versiyonu olarak düşünebilirsiniz.

UNIX veya Linux geçmişiniz varsa, reflog’u Git’in kabuk geçmişinin versiyonu olarak düşünebilirsiniz. Bu, oradaki şeylerin sadece "sizle" ve "oturumunuzla" için açıkça ilgili olduğunu vurgular ve aynı makinede çalışan başka birinin bununla ilgisi olmadığını belirtir.

Soy Referansları

Başka bir katkıyı belirtmenin ana yolu, onun kökenidir. Bir referansın sonuna bir ^ (caret) işareti koyarsanız, bunun Git’te temsil ettiği şey, o katkının öncelidir. Projenizin geçmişine bir göz atarsanız:

$ git log --pretty=format:'%h %s' --graph
* 734713b fixed refs handling, added gc auto, updated tests
*   d921970 Merge commit 'phedders/rdocs'
|\
| * 35cfb2b Some rdoc changes
* | 1c002dd added some blame and merge stuff
|/
* 1c36188 ignore *.gem
* 9b29157 add open3_detach to gemspec file list

Ardından, HEAD^ belirterek önceki katkıyı görebilirsiniz, bu da "HEAD’in önceli" anlamına gelir:

$ git show HEAD^
commit d921970aadf03b3cf0e71becdaab3147ba71cdef
Merge: 1c002dd... 35cfb2b...
Author: Scott Chacon <schacon@gmail.com>
Date:   Thu Dec 11 15:08:43 2008 -0800

    Merge commit 'phedders/rdocs'
Örnek 14. Windows’ta caret işaretinden kaçınmak

Windows’ta ^ işareti cmd.exe için özel bir karakterdir ve farklı şekilde işlenmelidir. Ya iki katına çıkarabilir ya da katkı referansını tırnak içine alabilirsiniz:

$ git show HEAD^     # will NOT work on Windows
$ git show HEAD^^    # OK
$ git show "HEAD^"   # OK

Kaçıncı önceli istediğinizi belirtmek için ^ karakterinin hemen ardından bir sayı belirtebilirsiniz: örneğin, d921970^2, "d921970’nin ikinci önceli" anlamına gelir. Bu sözdizimi, birden fazla önceli olan birleştirme katkıları için yararlıdır: bir birleştirme katkısının ilk önceli, birleştirdiğinizde üzerinde bulunduğunuz dalın (genellikle master) olduğu dal, bir birleştirme katkısının ikinci önceli ise birleştirilen dalın (örneğin, topic) olduğu daldır:

$ git show d921970^
commit 1c002dd4b536e7479fe34593e72e6c6c1819e53b
Author: Scott Chacon <schacon@gmail.com>
Date:   Thu Dec 11 14:58:32 2008 -0800

    added some blame and merge stuff

$ git show d921970^2
commit 35cfb2b795a55793d7cc56a6cc2060b4bb732548
Author: Paul Hedderly <paul+git@mjr.org>
Date:   Wed Dec 10 22:22:03 2008 +0000

    Some rdoc changes

Diğer ana soy belirteci de ~ (tilde) karakteridir. Bu da ilk öncele atıfta bulunur, bu yüzden HEAD~ ve HEAD^ eşdeğerdir. Fark, bir sayı belirttiğinizde ortaya çıkar. HEAD~2, "ilk öncelin önceli" veya "ikinci öncel" anlamına gelir - belirttiğiniz sayı kadar birinci önceli geçer. Örneğin, önceki listede, HEAD~3 şöyle olurdu:

$ git show HEAD~3
commit 1c3618887afb5fbcbea25b7c013f4e2114448b8d
Author: Tom Preston-Werner <tom@mojombo.com>
Date:   Fri Nov 7 13:47:59 2008 -0500

    ignore *.gem

Bu, HEAD~~~ olarak da yazılabilir, yani yine ilk öncelin ilk öncelidir.

$ git show HEAD~~~
commit 1c3618887afb5fbcbea25b7c013f4e2114448b8d
Author: Tom Preston-Werner <tom@mojombo.com>
Date:   Fri Nov 7 13:47:59 2008 -0500

    ignore *.gem

Bu sözdizimlerini birleştirebilirsiniz: (bir birleştirme katkısı olduğunu varsayarsak) önceki referansın ikinci önceline HEAD~3^2 kullanarak ulaşabilirsiniz, vs.

Katkı Aralığı

Şimdi tek tek katkıları belirtebildiğimize göre, katkı aralıklarını nasıl belirleyeceğimizi görelim. Özellikle dallarınızı yönetmek için oldukça kullanışlı bir yöntemdir: eğer birçok dalınız varsa, aralık belirlemelerini kullanarak "Bu dalda, henüz ana dalıma birleştirmediğim hangi işler var?" gibi soruları yanıtlayabilirsiniz.

İki Nokta (..)

Aralık belirtmekte kullanılan en yaygın sözdizimi "çift nokta"dır. Temel olarak Git’ten, bir katkıdan erişilebilen ancak diğerinden erişilemeyen bir katkı aralığını çözmesini istemektir. Örneğin, Aralık seçimi için örnek bir geçmiş. gibi bir katkı geçmiğiniz olsun:

Aralık seçimi için örnek bir geçmiş.
Görsel 136. Aralık seçimi için örnek bir geçmiş.

Diyelim ki experiment dalınızdan master dalınıza henüz birleştirilmemiş olan değişiklikleri görmek istiyorsunuz. Git’ten, master 'dan erişilemeyen ancak experiment 'ten erişilebilen tüm katkıların bir günlüğünü göstermesini isteyebilirsiniz; yani "experiment dalından erişilebilen ancak master dalından erişilemeyen tüm katkılar". Bu örneklerde kısaltma ve açıklık için, diyagramdaki katkı nesnelerinin harfleri gerçek günlük çıktısı yerine kullanılmıştır ve gösterilecek sırayla kullanılmıştır:

$ git log master..experiment
D
C

Öte yandan, tam tersini görmek istiyorsanız; yani experiment 'te olmayan tüm katkıları master 'da görmek istiyorsanız, dal isimlerini ters çevirebilirsiniz. experiment..master, experiment 'ten erişilemeyen her şeyi master 'da size gösterir:

$ git log experiment..master
F
E

Bu, experiment dalını güncel tutmak ve birleştirmek üzere olduğunuz şeyi önizlemek istiyorsanız kullanışlıdır. Bu sözdiziminin sık kullanılan bir başka kullanımı da, uzak bir repoya neyi iteceğinizi görmektir:

$ git log origin/master..HEAD

Bu komut size, mevcut dalınızda olup, origin uzak reposu master dalında olmayan tüm katkıları gösterir. Bir git push çalıştırırsanız ve mevcut dalınız origin/master 'ı takip ediyorsa, git log origin/master..HEAD tarafından listelenen katkılar, sunucuya aktarılacak olan katkılardır. Ayrıca, sözdiziminin bir tarafını bırakarak Git’in HEAD 'i varsaymasını sağlayabilirsiniz. Örneğin, git log origin/master.. yazarak önceki örnekteki aynı sonuçları alabilirsiniz; bir taraf eksikse, Git HEAD 'i otomatik olarak eksik kısmın yerine koyar.

Çoklu Noktalar

İki dalı belirtmek için "çift nokta" sözdizimi kullanışlı olabilir, ancak belki de mevcut daldan farklı olan birkaç dalı belirtmek istersiniz: örneğin, şu anda bulunduğunuz dalda olmayan birkaç dalda hangi katkıların olduğunu görmek gibi. Git, erişilebilir katkıları görmek istemediğiniz herhangi bir referansın önüne ^ karakterini veya --not kullanarak bunu yapmanıza izin verir. Bu nedenle, aşağıdaki üç komut eşdeğerdir:

$ git log refA..refB
$ git log ^refA refB
$ git log refB --not refA

Bunun güzelliği, bu sözdizimi ile sorgunuzda iki referanstan fazlasını belirtebilmenizdedir - bu çift nokta sözdizimi ile yapamadığınız bir şeydir. Örneğin, refA veya refB 'den erişilebilen ancak refC 'den erişilemeyen tüm katkıları görmek istiyorsanız, aşağıdaki komutlardan herhangi birini kullanabilirsiniz:

$ git log refA refB ^refC
$ git log refA refB --not refC

Bu, dallarınızdaki içeriği belirlemenize yardımcı olacak oldukça güçlü bir revizyon sorgu sistemi oluşturur.

Üçlü Nokta (…​)

Son büyük aralık seçimi sözdizimi üç noktalı yazımdır (…​), bu da iki referansın herhangi biri tarafından erişilebilen ancak her ikisinden erişilemeyen tüm katkıları belirtir. Aralık seçimi için örnek bir geçmiş. örneği katkı geçmişine geri dönün. master veya experiment 'te bulunan ancak ortak referanslardan herhangi birinde bulunmayan katkıları görmek istiyorsanız şunu çalıştırabilirsiniz:

$ git log master...experiment
F
E
D
C

Bu size yine normal log çıktısı verir, ancak sadece bu dört katkı için, geleneksel katkı tarihi sıralamasında görünür.

Bu durumda log komutu ile kullanılan yaygın bir anahtar değişimi --left-right 'dır: bu size her katkının, aralığın hangi tarafında olduğunu gösterir. Bu da, çıktıyı daha kullanışlı hale getirir:

$ git log --left-right master...experiment
< F
< E
> D
> C

Bu araçlarla, Git’e incelemek istediğiniz katkı veya katkıları belirtmeniz çok daha kolay olur.

scroll-to-top