Skip to content

Latest commit

 

History

History
147 lines (110 loc) · 8.72 KB

File metadata and controls

147 lines (110 loc) · 8.72 KB

Пошук

У базі коду, майже будь-якого розміру, часто потрібно з’ясувати, де функцію викликають, або де вона визначена, або знайти історію методу. Git пропонує декілька корисних інструментів для швидкого та легкого пошуку в коді та комітах, що були збережені в базі даних Git. Ми розглянемо деякі з них.

Git Grep

Git має команду під назвою grep, що дозволяє легко шукати в будь-якому дереві коміту або робочій теці заданий рядок або за регулярним виразом. У наступних прикладах ми будемо шукати в коді самого Git.

Без додаткових опцій, grep шукає тільки у файлах вашої робочої директорії. Якщо додати опцію -n, буде виведено номери рядків, в яких Git знайшов збіг.

$ 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:606:struct tm *gmtime_r(const time_t *timep, struct tm *result)
compat/mingw.h:162:struct tm *gmtime_r(const time_t *timep, struct tm *result);
date.c:429:             if (gmtime_r(&now, &now_tm))
date.c:492:             if (gmtime_r(&time, tm)) {
git-compat-util.h:721:struct tm *git_gmtime_r(const time_t *, struct tm *);
git-compat-util.h:723:#define gmtime_r git_gmtime_r

У команди grep є багато цікавих опцій.

Наприклад, замість попереднього виклику, можна отримати від Git підсумок, що показує в яких файлах є збіги та скільки їх у кожному файлі, за допомогою опції --count:

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

Якщо бажаєте дізнатись, в якому методі чи функції ймовірно знайдено збіг, то скористайтесь -p:

$ git grep -p gmtime_r *.c
date.c=static int match_multi_number(unsigned long num, char c, const char *date, char *end, struct tm *tm)
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)) {

Отже тут ми можемо бачити, що gmtime_r викликається з функцій match_multi_number та match_digit у файлі date.c.

Також можна шукати складні комбінації рядків за допомогою опції --and, яка надає можливість шукати декілька збігів разом в одному рядку. Наприклад, пошукаймо рядки, що визначають константу з рядками LINK'' або BUF_MAX'' в них у коді Git у версіях старіших за 1.8.0.

Ми також використаємо опції --bread та --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, а не тільки в робочій директорії. Як ми бачили в останньому прикладі, ми шукали щось у старіших версіях коду Git, а не в поточній вибраній версії.

Пошук у журналі Git

Напевно вас цікавить не тільки де щось існує, а ще й коли воно існувало або з’явилося. Команда git log пропонує декілька потужних інструментів для пошуку окремих комітів за змістом їх повідомлень або навіть змістом різниці, яку вони додали.

Якщо ви бажаєте дізнатись, наприклад, коли константа ZLIB_BUF_MAX з’явилася, ви можете попросити Git показати виключно коміти, які або додали, або вилучили рядок, за допомогою опції -S.

$ 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.

Рядковий пошук у журналі

Ще однин доволі складний пошук журналу, що може бути дивовижно корисним — це рядковий пошук історії. Це доволі новий функціонал і ще не дуже широковживаний, проте він може бути дійсно корисним. Його можна викликати за допомогою опції -L команди git log, і тоді вам буде показана історія функції або рядка коду вашої бази коду.

Наприклад, якщо ми бажаємо побачити кожну зміну функції git_deflate_bount з файлу zlib.c, то ми можемо виконати git log -L :git_deflate_bound:zlib.c. Тоді Git спробує зрозуміти, де межі цієї функції та буде проглядати історію, ті покаже нам кожну зміну, що була зроблена в цій функції у вигляді послідовності патчів аж до моменту створення цієї функції.

$ git log -L :git_deflate_bound:zlib.c
commit ef49a7a0126d64359c974b4b3b71d7ad42ee3bca
Author: Junio C Hamano <[email protected]>
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 <[email protected]>
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 не може знайти функцію чи метод вашої мови програмування, ви також можете надати регулярний вираз. Наприклад, ця команда має зробити те ж саме: git log -L '/unsigned long git_deflate_bound/',/^}/:zlib.c. Ви також можете дати інтервал рядків або один номер рядка, щоб побачити подібний вивід.