-
1. 시작하기
-
2. Git의 기초
- 2.1 Git 저장소 만들기
- 2.2 수정하고 저장소에 저장하기
- 2.3 커밋 히스토리 조회하기
- 2.4 되돌리기
- 2.5 리모트 저장소
- 2.6 태그
- 2.7 Git Alias
- 2.8 요약
-
3. Git 브랜치
-
4. Git 서버
- 4.1 프로토콜
- 4.2 서버에 Git 설치하기
- 4.3 SSH 공개키 만들기
- 4.4 서버 설정하기
- 4.5 Git 데몬
- 4.6 스마트 HTTP
- 4.7 GitWeb
- 4.8 GitLab
- 4.9 또 다른 선택지, 호스팅
- 4.10 요약
-
5. 분산 환경에서의 Git
- 5.1 분산 환경에서의 워크플로
- 5.2 프로젝트에 기여하기
- 5.3 프로젝트 관리하기
- 5.4 요약
-
6. GitHub
- 6.1 계정 만들고 설정하기
- 6.2 GitHub 프로젝트에 기여하기
- 6.3 GitHub 프로젝트 관리하기
- 6.4 Organization 관리하기
- 6.5 GitHub 스크립팅
- 6.6 요약
-
7. Git 도구
- 7.1 리비전 조회하기
- 7.2 대화형 명령
- 7.3 Stashing과 Cleaning
- 7.4 내 작업에 서명하기
- 7.5 검색
- 7.6 히스토리 단장하기
- 7.7 Reset 명확히 알고 가기
- 7.8 고급 Merge
- 7.9 Rerere
- 7.10 Git으로 버그 찾기
- 7.11 서브모듈
- 7.12 Bundle
- 7.13 Replace
- 7.14 Credential 저장소
- 7.15 요약
-
8. Git맞춤
- 8.1 Git 설정하기
- 8.2 Git Attributes
- 8.3 Git Hooks
- 8.4 정책 구현하기
- 8.5 요약
-
9. Git과 여타 버전 관리 시스템
- 9.1 Git: 범용 Client
- 9.2 Git으로 옮기기
- 9.3 요약
-
10. Git의 내부
- 10.1 Plumbing 명령과 Porcelain 명령
- 10.2 Git 개체
- 10.3 Git Refs
- 10.4 Packfile
- 10.5 Refspec
- 10.6 데이터 전송 프로토콜
- 10.7 운영 및 데이터 복구
- 10.8 환경변수
- 10.9 요약
-
A1. 부록 A: 다양한 환경에서 Git 사용하기
- A1.1 GUI
- A1.2 Visual Studio
- A1.3 Eclipse
- A1.4 Bash
- A1.5 Zsh
- A1.6 Git in Powershell
- A1.7 요약
-
A2. 부록 B: 애플리케이션에 Git 넣기
-
A3. 부록 C: Git 명령어
- A3.1 설치와 설정
- A3.2 프로젝트 가져오기와 생성하기
- A3.3 스냅샷 다루기
- A3.4 Branch와 Merge
- A3.5 공유하고 업데이트하기
- A3.6 보기와 비교
- A3.7 Debugging
- A3.8 Patch 하기
- A3.9 Email
- A3.10 다른 버전 관리 시스템
- A3.11 관리
- A3.12 Plumbing 명령어
7.5 Git 도구 - 검색
검색
프로젝트가 크든 작든 함수의 정의나 함수가 호출되는 곳을 검색해야 하는 경우가 많다. 함수의 히스토리를 찾아보기도 한다. Git은 데이터베이스에 저장된 코드나 커밋에서 원하는 부분을 빠르고 쉽게 검색하는 도구가 여러 가지 있으며 앞으로 함께 살펴보자.
Git Grep
Git의 grep
명령을 이용하면 커밋 트리의 내용이나 워킹 디렉토리의 내용을 문자열이나 정규표현식을 이용해 쉽게 찾을 수 있다.
Git 소스를 예로 들어 명령을 어떻게 사용하는지 알아보자.
기본적으로 대상을 지정하지 않으면 워킹 디렉토리의 파일에서 찾는다.
명령을 실행할 때 -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
git grep
명령에서 쓸만한 몇 가지 옵션을 좀 더 살펴보자.
예를 들어 위의 결과 대신 어떤 파일에서 몇 개나 찾았는지만 알고 싶다면 -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 히스토리 내의 어떠한 정보라도 찾아낼 수 있다.
위의 예제에서 이전 버전의 소스에서도 특정 단어를 찾아낸 것을 볼 수 있다.
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
옵션으로 정규표현식을 써서 검색하면 된다.
라인 로그 검색
진짜 미친 듯이 좋은 로그 검색 도구가 또 있다. 라인 히스토리 검색이다.
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
명령으로 위와 같은 결과를 볼 수 있다.
한 라인의 히스토리만 검색할 수도 있고 여러 라인에 걸친 히스토리를 검색할 수도 있다.