Git
Chapters ▾ 2nd Edition

7.5 Гит алати - Претрага

Претрага

Без обзира на величину пројекта, често ћете имати потребу да пронађете место на којем је функција дефинисана или на којем се позива, или да пронађете историју неке методе. Програм Гит вам обезбеђује неколико корисних алата за брзу и лаку претрагу кода и комитова који су сачувани у његовој бази података. Приказаћемо неколико тих команди.

Git Grep

Програм Гит се испоручује са командом под називом grep која вам омогућава да једноставно претражујете било које комитовано стабло или радни директоријум на стринг или регуларни израз. У наредним примерима ћемо претраживати кôд самог програма Гит.

Команда git grep ће подразумевано да претражује све фајлове у вашем радном директоријуму. Као прву варијацију можете јој проследити -n тако да исписује бројеве линија у којима је програм Гит пронашао подударања.

$ 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

Уз основну претрагу која је приказана изнад, команда git grep нуди и велики број осталих интересантних опција.

На пример, уместо претходног позива, програму Гит опцијом --count можете наложити да испис сажме тако да вам прикаже само у којим фајловима постоје подударања и колико подударања је пронашао у сваком од фајлова:

$ 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

Ако вас интересује контекст траженог стринга, методу или функцију која га обухвата можете за сваки подударени стринг добити опцијом -p или --show-function:

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

Као што видите, рутина gmtime_r се позива и у match_multi_number и у match_digit функцији у фајлу date.c (треће приказано подударање представља само стринг који се јавља у коментару).

Такође можете да тражите и сложене комбинације стрингова заставицом --and која обезбеђује да се вишеструка подударања налазе у истој линији. На пример, хајде да потражимо било које линије које дефинишу константу са једним од подстрингова „LINK” или „BUF_MAX” у одређеној старијој верзији Гит кода коју представља ознака`v1.8.0` (укључићемо и опције --break и --heading које помажу да се излаз издели у читљивији формат):

$ 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 има неколико предности у односу на обичне команде претраге као што су grep и ack. Прва је да је то да је заиста веома брза, а друга да можете вршити претрагу кроз било које Гит стабло, не само по радном директоријуму. Као што смо видели у горњем примеру, појмове смо тражили у старијој верзији изворног кода програма Гит, а не у верзији која је тренутно одјављена.

Git Log претрага

Можда не тражите место на којем се налази појам, већ време* у којем је постојао или када је уведен. Команда git log има више моћних алата за проналажење одређених комитова према садржају њихових комит порука или чак према садржају разлике коју уводе.

На пример, ако желимо да пронађемо када је по први пут уведена константа ZLIB_BUF_MAX, програму Гит опцијом -S (колоквијално названој „пијук” тј. pickaxe програма Гит) можемо наложити да нам прикаже само комитове који су изменили број појављивања тог стринга.

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

Ако погледамо разлике тих комитова, можемо видети да је у ef49a7a уведена константа и да је у e01503b измењена.

Ако је потребно да будете још одређенији, опцијом -G можете задати регуларни израз по којем ће се вршити претрага.

Линијска претрага лога

Још једна прилично напредна претрага лога је невероватно корисна линијска претрага лога. Једноставно покрените git log са опцијом -L и приказаће вам се историја функције или линије кода у вашем пројекту.

На пример, ако желимо да видимо сваку измену функције git_deflate_bound у фајлу zlib.c, извршили бисмо git log -L :git_deflate_bound:zlib.c. То ће покушати да одреди шта су границе те функције, па ће онда претражити историју и приказаће нам сваку измену која је учињена над функцијом као низ закрпа почевши од тренутка када је функција креирана.

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

Ако програм Гит за ваш програмски језик не може да одреди како да подудари функцију или методу, можете му помоћи тако што ћете навести регуларни израз. На пример, следеће би урадило исту ствар као и горњи пример: git log -L '/unsigned long git_deflate_bound/',/^}/:zlib.c. Такође можете да јој проследите и опсег линија или један број линије и вратиће вам исту врсту приказа.