Git
Chapters ▾ 2nd Edition

7.5 Mga Git na Kasangkapan - Paghahanap

Paghahanap

Sa halos lahat ng anumang laki ng codebase, ikaw ay madalas kailangan na maghanap kung saan ang function tinawag o binigyang-kahulugan, o pinakita ang kasaysayan ng pamamaraan. Ang Git ay nagbibigay ng isang pares ng kapaki-pakinabang na mga kasangkapan para tingnan ng maayos ang code at mga commit na naka-imbak sa kanyang database nang mabilis at madali. Tayo ay dumaan sa iilan sa kanila.

Git Grep

Ang git ay nagpapadala ng isang uto na tinatawag na grep na nagpapahintulot sayo na madaling hanapin ng maayos ang anumang na-commit na tree o ang tinatrabahong direktoryo para sa isang string o regular expression. Para sa mga halimbawa na sumusunod, maghahanap tayo sa source para sa Git mismo.

Bilang default, ang git grep ay tumingin ng maayos sa mga file sa iyong tinatrabahong direktoryo. Bilang unang pagkakaiba-iba, maaari mong gamitin ang alinman sa -n o --line-number na mga opsyon upang i-print out ang mga linyang naka-numero na kung saan si Git ay nakahanap ng magkapareho:

$ 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

Bilang karagdagan sa pangunahing paghahanap na ipinakita sa itaas, ang git grep ay sumusuporta sa karamihan sa ibang kawili-wili na mga opsyon.

Halimbawa, sa halip na i-print ang lahat ng tumugma, maaari mong tanungin ang git grep upang gumawa ng buod ng output sa pamamagitan sa pagpakita sa iyo kung anong mga file lamang ang naglalaman sa hinahanap na string at gaano karami ang tumutugma sa bawat file na gamit ang -c or --count na opsyon:

$ 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

Kung interesado ka sa konteksto sa isang hinahanap na string, maaari mong ipakita ang kalakip na pamamaraan o function para sa bawat tumutugma na string na alinman sa -p or --show-function na mga opsyon:

$ 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 */

Tulad ng iyong nakikita, ang gmtime_r na karaniwang gawain ay tumatawag mula sa kapwa na match_multi_number at match_digit na mga function sa date.c na file (ang pangatlong tumugma na naipakita ay kumakatawan lamang sa string na lumilitaw sa isang komento).

Maaari ka ring maghanap para sa kumplikadong mga kumbinasyon sa mga string na may --and na flag, na tinitiyak na ang maramihang tumutugma ay dapat nangyayari sa parehong linya sa teksto. Halimbawa, tingnan natin ang anumang mga linya na tumutukoy sa isang pare-parehong pangalan na naglalaman alinman sa mga substring ang “LINK” o “BUF_MAX”, partikular sa isang lumang bersyon sa Git codebase na kinakatawan ng tag v1.8.0 (idagdag natin sa --break and --heading na mga opsyon na kung saan ay tumutulong sa paghiwalay sa output sa isang higit pa nababasang format):

$ 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 */

Ang git grep na utos ay mayroong iilang mga pakinabang kung ating ihambing sa normal na paghahanap na mga utos tulad ng grep at ack. Ang una ay ito ay napakabilis, ang ikalawa ay ikaw ay makahanap ng maayos sa anumang tree sa Git, hindi lamang ang tinatrabahong direktoryo. Sa nakikita natin sa itaas na halimbawa, naghanap tayo ng mga termino sa isang mas lumang bersyon ng Git na source code, hindi ang bersyon na kasalukuyang naka-check out.

Ang Paghahanap sa Git Log

Marahil ang hinahanap mo ay hindi para sa kung saan isang termino ang umiiral, ngunit kapag ito ay umiiral o ipinakilala. Ang git log na utos ay mayroong bilang sa malakas na mga kasangkapan para humanap sa tiyak na mga commit sa pamamagitan ng nilalaman sa kanilang mga mensahe o kahit na ang nilalaman ng diff ay ipinakilala nila.

Kung, halimbawa, gusto namin na malaman na kapag ang ZLIB_BUF_MAX na constant ay orihinal na ipinakilala, maaari nating gamitin ang -S na opsyon (colloquially na tumutukoy bilang Git “pickaxe” na opsyon) para sabihan ang Git na ipakita lamang ang mga commit na nakapagbago sa bilang ng paglitaw ng string na iyon.

$ 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

Kung titingnan natin ang diff ng mga commit na iyon, maaari naming makita na sa ef49a7a ang constant ay ipinakilala at sa e01503b ito ay binago.

Kung kailangan mo ng mas tiyak, maaari nating makita na sa regular na expression upang mahanap ang mayroong -G na opsyon.

Linya sa Log ng Paghahanap

Isa pang patas na advanced na log sa paghanap na grabeng kapaki-pakinabang ay ang linya sa kasaysayan ng paghahanap. Simpleng patakbuhin ang git log na may -L na opsyon, at ito ay magpapakita sa iyo ng kasaysayan ng isang function o linya ng code sa iyong codebase.

Halimbawa, kung gusto nating makita ang bawat pagbabago na ginawa sa function na git_deflate_bound sa zlib.c na file, maaari nating ipatakbo ang git log -L :git_deflate_bound:zlib.c. Ito ay sinusubukan na malaman kung anong mga hangganan ng function na iyon at tiningnan ang kasaysayan at ipapakita sa atin ang bawat pagbabago na nagawa sa function bilang isang serye ng mga patch na ibalik kung kailan ang function ay unang nilikha.

$ 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);
+}
+

Kung ang Git ay hindi malaman kung papaano tumugma ang isang function o pamamaraan sa iyong programming language, maaari ka ring magbigay nito na may regular na expression (or regex). Halimbawa, ito ay natapos sana kung parehong bagay na halimbawa sa itaas: git log -L '/unsigned long git_deflate_bound/',/^}/:zlib.c. Maaari mo ring bigyan ito ng lawak ng mga linya o isang solong mga linya o isang solong numero ng linya at magkakaroon ka ng parehong uri ng output.