Git
Chapters ▾ 2nd Edition

7.5 Git Tools - Arama

Arama

Herhangi bir boyuttaki bir kod tabanında, genellikle bir fonksiyonun nerede tanımlandığını veya çağrıldığını bulmanız, ya da bir mesela bir metodun geçmişini göstermeniz gerekebilir. Git, kendi veritabanına kayıtlı kod ve katkıları, hızlı ve kolay bir şekilde bulmanızı sağlayan birkaç kullanışlı araç sunar. Şimdi bunlardan birkaçını ele alalım.

Git Grep

Git, katkılanmış herhangi bir ağaç, çalışma dizini, hatta bir dize veya düzenli ifade (regex) için kolayca arama yapmanıza olanak tanıyan grep adlı bir komutla birlikte gelir. Aşağıdaki örnekler için, Git’in kendi kaynak kodu içinde arama yapacağız.

git grep, varsayılan olarak çalışma dizininizdeki dosyalarda arama yapacaktır. İlk varyant olarak, eşleşmelerin bulunduğu satır numaralarını yazdırmak için -n veya --line-number seçeneklerinden birini kullanabilirsiniz:

$ git grep -n gmtime_r
compat/gmtime.c:3:#undef gmtime_r
compat/gmtime.c:8:      return git_gmtime_r(timep, &result);
compat/gmtime.c:11:struct tm *git_gmtime_r(const time_t *timep, struct tm *result)
compat/gmtime.c:16:     ret = gmtime_r(timep, result);
compat/mingw.c:826:struct tm *gmtime_r(const time_t *timep, struct tm *result)
compat/mingw.h:206:struct tm *gmtime_r(const time_t *timep, struct tm *result);
date.c:482:             if (gmtime_r(&now, &now_tm))
date.c:545:             if (gmtime_r(&time, tm)) {
date.c:758:             /* gmtime_r() in match_digit() may have clobbered it */
git-compat-util.h:1138:struct tm *git_gmtime_r(const time_t *, struct tm *);
git-compat-util.h:1140:#define gmtime_r git_gmtime_r

Yukarıda gösterilen temel arama işlemine ek olarak, git grep birçok başka ilginç seçenek de destekler.

Örneğin, tüm eşleşmeleri yazdırmak yerine, git grep komutuna, arama dizesini içeren yalnızca hangi dosyaların olduğunu ve her dosyada kaç eşleşme olduğunu göstermesi için -c veya --count seçeneğini ekleyebilirsiniz:

$ git grep --count gmtime_r
compat/gmtime.c:4
compat/mingw.c:1
compat/mingw.h:1
date.c:3
git-compat-util.h:2

Eğer bir arama dizesinin bağlamını görmek istiyorsanız, her eşleşen dize için kapsayıcı yöntemi veya fonksiyonu göstermek için -p veya --show-function seçeneklerinden birini ekleyebilirsiniz:

$ git grep -p gmtime_r *.c
date.c=static int match_multi_number(timestamp_t num, char c, const char *date,
date.c:         if (gmtime_r(&now, &now_tm))
date.c=static int match_digit(const char *date, struct tm *tm, int *offset, int *tm_gmt)
date.c:         if (gmtime_r(&time, tm)) {
date.c=int parse_date_basic(const char *date, timestamp_t *timestamp, int *offset)
date.c:         /* gmtime_r() in match_digit() may have clobbered it */

Gördüğünüz gibi, gmtime_r rutini date.c dosyasındaki match_multi_number ve match_digit fonksiyonlarından çağrılır (üçüncü eşleşme, sadece bir yorum satırında görünen dizedir).

Ayrıca, --and bayrağıyla karmaşık dize kombinasyonlarını arayabilirsiniz, bu da birden fazla eşleşmenin aynı metin satırında gerçekleşmesini sağlar. Örneğin: özellikle, v1.8.0 etiketi ile temsil edilen Git kod tabanının eski bir sürümünde, içeriğinde ya ``LINK`` ya da ``BUF_MAX`` alt dizelerinden herhangi biri bulunan bir sabiti tanımlayan, herhangi bir satırı arayalım (çıktıyı daha okunabilir bir formata ayırmaya yardımcı olan --break ve --heading seçeneklerini de ekleyeceğiz):

$ git grep --break --heading \
    -n -e '#define' --and \( -e LINK -e BUF_MAX \) v1.8.0
v1.8.0:builtin/index-pack.c
62:#define FLAG_LINK (1u<<20)

v1.8.0:cache.h
73:#define S_IFGITLINK  0160000
74:#define S_ISGITLINK(m)       (((m) & S_IFMT) == S_IFGITLINK)

v1.8.0:environment.c
54:#define OBJECT_CREATION_MODE OBJECT_CREATION_USES_HARDLINKS

v1.8.0:strbuf.c
326:#define STRBUF_MAXLINK (2*PATH_MAX)

v1.8.0:symlinks.c
53:#define FL_SYMLINK  (1 << 2)

v1.8.0:zlib.c
30:/* #define ZLIB_BUF_MAX ((uInt)-1) */
31:#define ZLIB_BUF_MAX ((uInt) 1024 * 1024 * 1024) /* 1GB */

git grep komutunun, grep ve ack gibi normal arama komutlarına göre birkaç avantajı vardır. İlk olarak, gerçekten hızlıdır; ikincisi ise, yalnızca çalışma dizinini değil, Git’teki herhangi bir ağacı arayabilirsiniz. Yukarıdaki örnekte gördüğümüz gibi, Git kaynak kodunun daha eski bir sürümünde terimleri aradık, güncel sürümde değil.

Git Günlük (log) Araması

Belki bir terimin nerede olduğu değil, ne zaman var olduğu veya tanıtıldığına bakmak istiyorsunuz. git log komutu, belirli katkıları, katkı mesajlarının içeriği veya tanıttıkları fark içeriği ile bulmak için bir dizi güçlü araca sahiptir.

Örneğin, ZLIB_BUF_MAX sabitinin orijinal olarak ne zaman tanıtıldığını bulmak istiyorsak, Git’e sadece o dizenin tekrar sayısını değiştiren katkıları göstermesini söylemek için -S seçeneğini (genellikle Git "kazma (pickaxe)" seçeneği olarak adlandırılır) kullanabiliriz.

$ git log -S ZLIB_BUF_MAX --oneline
e01503b zlib: allow feeding more than 4GB in one go
ef49a7a zlib: zlib can only process 4GB at a time

Bu katkıların farkına baktığımızda, ef49a7a katkısında sabitin tanıtıldığını ve e01503b katkısında değiştirildiğini görebiliriz.

Daha belirleyici olmanız gerekiyorsa, -G seçeneği ile aramak için bir düzenli ifade (regex) girebilirsiniz.

Çizgisel Günlük (log) Araması

Başka oldukça gelişmiş bir günlük araması da inanılmaz derecede faydalı olan "çizgisel geçmiş aramasıdır". Basitçe git log komutunu -L seçeneği ile çalıştırın: kod tabanınızdaki bir fonksiyonun veya kod satırının geçmişini gösterecektir.

Örneğin, zlib.c dosyasındaki git_deflate_bound fonksiyonuna yapılan her değişikliği görmek istersek, git log -L :git_deflate_bound:zlib.c komutunu çalıştırabiliriz. Bu komut, bu işlevin sınırlarını bulmaya çalışacak ve ardından geçmişi inceleyerek, fonksiyonun ilk oluşturulduğu zamana kadar yapılan her değişikliği bize yama serisi olarak gösterecektir.

$ git log -L :git_deflate_bound:zlib.c
commit ef49a7a0126d64359c974b4b3b71d7ad42ee3bca
Author: Junio C Hamano <gitster@pobox.com>
Date:   Fri Jun 10 11:52:15 2011 -0700

    zlib: zlib can only process 4GB at a time

diff --git a/zlib.c b/zlib.c
--- a/zlib.c
+++ b/zlib.c
@@ -85,5 +130,5 @@
-unsigned long git_deflate_bound(z_streamp strm, unsigned long size)
+unsigned long git_deflate_bound(git_zstream *strm, unsigned long size)
 {
-       return deflateBound(strm, size);
+       return deflateBound(&strm->z, size);
 }


commit 225a6f1068f71723a910e8565db4e252b3ca21fa
Author: Junio C Hamano <gitster@pobox.com>
Date:   Fri Jun 10 11:18:17 2011 -0700

    zlib: wrap deflateBound() too

diff --git a/zlib.c b/zlib.c
--- a/zlib.c
+++ b/zlib.c
@@ -81,0 +85,5 @@
+unsigned long git_deflate_bound(z_streamp strm, unsigned long size)
+{
+       return deflateBound(strm, size);
+}
+

Eğer Git programlama dilinizde bir fonksiyonu veya metodu nasıl eşleştireceğini bulamazsa, ona bir düzenli ifade (veya regex) sağlayabilirsiniz. Mesela, şu örnek yukarıdaki örnekle aynı işi yapardı: git log -L '/unsigned long git_deflate_bound/',/^}/:zlib.c. Ayrıca, ona bir dize satır aralığı veya tek bir satır numarası verebilirsiniz ve aynı türde bir çıktı alırsınız.

scroll-to-top