Pro git - 7.5
Updated:
Pro git - 검색
-
프로젝트가 크든 작든 함수의 정의나 함수가 호출되는 곳을 검색해야 하는 경우가 많다.
- 함수의 히스토리를 찾아보기도 한다.
- Git은 데이터베이스에 저장된 코드나 커밋에서 원하는 부분을 빠르고 쉽게 검색하는 도구가 여러 가지 있으며 앞으로 함께 살펴보자.
1. Git Grep
- Git의
grep
명령을 이용하면 커밋 트리의 내용이나 워킹 디렉토리의 내용을 문자열이나 정규표현식을 이용해 쉽게 찾을 수 있다. - 기본적으로 대상을 지정하지 않으면 워킹 디렉토리의 파일에서 찾는다.
- 명령을 실행할 때
-n
또는--line-number
옵션을 추가하면 찾을 문자열이 위치한 라인 번호도 같이 출력한다.
$ 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
- 위의 결과 대신 어떤 파일에서 몇 개나 찾았는지만 알고 싶다면
-c
또는--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
함수를date.c
파일에서match_multi_number
,match_digit
함수에서 호출하고 있다는 걸 확인할 수 있다(세 번째로 호출하는 결과는 주석 안에 있는 것을 확인할 수 있다). --and
옵션을 이용해서 여러 단어가 한 라인에 동시에 나타나는 줄 찾기 같은 복잡한 조합으로 검색할 수 있다.- 예를 들어 “LINK” 나 “BUF_MAX” 둘 중 하나를 포함한 상수 정의를 1.8.0 이전 버전의 Git 소스 코드에서 검색하는 것을 할 수 있다(
--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 히스토리 내의 어떠한 정보라도 찾아낼 수 있다.
- 위의 예제에서 이전 버전의 소스에서도 특정 단어를 찾아낸 것을 볼 수 있다.
2. Git 로그 검색
- 어떤 변수가 어디에 있는지를 찾아보는 게 아니라, 히스토리에서 언제 추가되거나 변경됐는지 찾아볼 수도 있다.
-
git log
명령을 이용하면 Diff 내용도 검색하여 어떤 커밋에서 찾고자 하는 내용을 추가했는지 찾을 수 있다. ZLIB_BUF_MAX
라는 상수가 가장 처음 나타난 때를 찾는 문제라면-S
옵션(“pickaxe(곡괭이)” 옵션이라 한다)을 이용해 해당 문자열이 추가된 커밋과 없어진 커밋만 검색할 수 있다.
$ 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
-
위 두 커밋의 변경 사항을 살펴보면
ef49a7a
에서ZLIB_BUF_MAX
상수가 처음 나오고e01503b
에서는 변경된 것을 알 수 있다. -
더 세세한 조건을 걸어 찾고 싶다면 로그를 검색할 때
-G
옵션으로 정규표현식을 써서 검색하면 된다.
2.1 라인 로그 검색
- 진짜 미친 듯이 좋은 로그 검색 도구가 또 있다.
-
라인 히스토리 검색이다.
git log
를 쓸 때-L
옵션을 붙이면 어떤 함수나 한 라인의 히스토리를 볼 수 있다. - 예를 들어,
zlib.c
파일에 있는git_deflate_bound
함수의 모든 변경 사항들을 보길 원한다고 생각해보자. git log -L :git_deflate_bound:zlib.c
라고 명령 실행하면 된다.- 이 명령을 실행하면 함수의 시작과 끝을 인식해서 함수에서 일어난 모든 히스토리를 함수가 처음 만들어진 때부터 Patch를 나열하여 보여준다.
$ 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이 함수의 처음과 끝을 인식하지 못할 때는 정규표현식으로 인식하게 할 수도 있다.
git log -L '/unsigned long git_deflate_bound/',/^}/:zlib.c
명령으로 위와 같은 결과를 볼 수 있다.- 한 라인의 히스토리만 검색할 수도 있고 여러 라인에 걸친 히스토리를 검색할 수도 있다.