Git
Chapters ▾ 2nd Edition

7.5 Orodja Git - Iskanje

Iskanje

V vsaki kodi različnih velikosti boste pogostokrat morali najti, kje je funkcija klicana ali definirana, ali pa prikazati zgodovino metode. Git ponuja nekaj uporabnih orodij za hitro in enostavno iskanje po kodi in potrditvah, shranjenih v njegovi bazi podatkov. Pregledali bomo nekaj izmed njih.

Git grep

Git vključuje ukaz grep, s katerim lahko enostavno iščete po katerem koli potrjenem drevesu, delovnem imeniku ali celo indeksu za niz ali redni izraz. Za primere, ki sledijo, bomo iskali po izvorni kodi samega Gita.

Privzeto git grep išče po datotekah v delovnem imeniku. Kot prvo variacijo lahko uporabite možnosti -n ali --line-number, da izpišete številke vrstic, kjer je Git našel zadetke:

$ 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

Poleg osnovnega iskanja, prikazanega zgoraj, git grep podpira številne druge zanimive možnosti.

Namesto izpisovanja vseh zadetkov lahko na primer git grep z možnostjo -c ali --count zaprosite, da povzame izhod tako, da vam pokaže le datoteke, ki vsebujejo iskalni niz, in koliko zadetkov je bilo v vsaki datoteki:

$ 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 vas zanima kontekst iskanega niza, lahko z uporabo možnosti -p ali --show-function prikažete objemajočo metodo ali funkcijo za vsak prilegajoči se niz:

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

Kot vidite, se rutina gmtime_r kliče iz funkcij match_multi_number in match_digit v datoteki date.c (tretji zadetek predstavlja samo niz, ki se pojavi v komentarju).

Iščete lahko tudi zapletene kombinacije nizov z zastavico --and, ki zagotavlja, da se morajo večkratni zadetki pojaviti v isti vrstici besedila. Na primer, poiščimo vse vrstice, ki določajo konstanto, katere ime vsebuje katerega koli od podnizov »LINK« ali »BUF_MAX«, posebej v starejši različici kode Git, ki jo predstavlja oznaka v1.8.0 (dodali bomo možnosti --break in --heading, ki pomagata razdeliti izpis v bolj berljiv 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 */

Ukaz git grep ima nekaj prednosti pred običajnimi ukazi za iskanje, kot sta grep in ack. Prva prednost je, da je zelo hiter, druga pa je, da lahko iščete skozi katero koli drevo v Gitu, ne le po delovnem imeniku. Kot smo videli v zgornjem primeru, smo iskali izraze v starejši različici izvorne kode Git in ne le v trenutno izvlečeni različici.

Iskanje po dnevniku Gita

Morda ne iščete kje obstaja izraz, ampak kdaj je obstajal, ali bil uveden. Ukaz git log ima več zmogljivih orodij za iskanje specifičnih potrditev glede na vsebino njihovih sporočil ali celo vsebino razlik, ki jih predstavljajo.

Na primer, če želimo ugotoviti, kdaj je bila prvotno uvedena konstanta ZLIB_BUF_MAX, lahko uporabimo možnost -S (pogovorno imenovana kot Gitova možnost »krampa in lopate«), da Gitu povemo, naj nam prikaže le tiste potrditve, ki so spremenile število pojavitev tega niza.

$ 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

Če si ogledamo razliko teh potrditev, lahko vidimo, da je bila konstanta uvedena v ef49a7a, v e01503b pa spremenjena.

Če želite biti natančnejši, lahko z možnostjo -G podate regularni izraz, ki ga iščete.

Iskanje po vrsticah dnevnika

Druga precej napredna funkcija iskanja po dnevniku, ki je izjemno uporabna, je iskanje zgodovine vrstic. Preprosto poženite git log z možnostjo -L in prikazal vam bo zgodovino funkcije ali vrstice kode v vaši kodni bazi.

Na primer, če bi radi videli vsako spremembo funkcije git_deflate_bound v datoteki zlib.c, bi pognali git log -L :git_deflate_bound:zlib.c. To bo poskusilo ugotoviti meje te funkcije in nato pregledalo zgodovino ter nam prikazalo vsako spremembo funkcije kot zaporedje popravkov, vse do prvotnega ustvarjanja funkcije.

$ 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 Git ne more ugotoviti, kako prilegati funkcijo ali metodo v vašem programskem jeziku, mu lahko podate tudi regularni izraz (ali regex). Na primer, to bi storilo enako kot zgornji primer: git log -L '/unsigned long git_deflate_bound/',/^}/:zlib.c. Lahko mu podate tudi razpon vrstic, ali pa eno samo vrstico in dobili boste podoben izpis.

scroll-to-top