목차10개 항목
출처와 참고
arslanbilal의 「Git and Git Flow Cheat Sheet」와 mingrammer의 「Git Tips」(git-tips/tips 한국어판)에서 검색·이력 항목을 모아, 옵션은 Git 공식 문서로 확인해 질문별로 재구성한 노트다.
--cherry-pick 비교와 tag --contains는 「Git Flight Rules」를 바탕으로 보강했다.
무엇을 찾느냐에 따라 명령이 다르다
| 질문 | 명령 |
|---|---|
| 지금 코드 어디에 이 문자열이 있나 | git grep |
| 이 문자열이 언제 생기거나 사라졌나 | git log -S / -G (pickaxe) |
| 이 함수·줄 범위가 어떻게 바뀌어 왔나 | git log -L |
| 이 줄을 마지막으로 누가 왜 바꿨나 | git blame |
| 언제부터 버그가 생겼나 | git bisect |
| 커밋 메시지·작성자·기간으로 찾기 | git log --grep, --author, --since |
| 이 브랜치에만 있는 커밋, 아직 안 올린 커밋 | 범위 표기 A..B |
범위 표기: 어느 커밋들을 볼까
log·diff 같은 명령은 커밋 범위를 받는다. 범위 표기를 알면 대부분의 "어느 커밋이 어디에 있나" 질문이 풀린다.
| 표기 | 뜻 | 예 |
|---|---|---|
A..B | B에서 닿는 커밋 중 A에서는 닿지 않는 것 | git log main..feature: feature에만 있는 커밋 |
B ^A | A..B와 같다. 여러 개를 뺄 때 편하다 | git log feature ^main ^release |
A...B | 둘 중 한쪽에만 있는 커밋(대칭 차집합) | git log --left-right main...feature: <·>로 어느 쪽 것인지 표시 |
@{u} | 현재 브랜치의 업스트림(추적 원격 브랜치) | git log @{u}..: 아직 push 안 한 커밋 |
HEAD~3, HEAD^2 | 첫 부모를 3번 거슬러 / 두 번째 부모 | merge 커밋의 부모는 Git 브랜치 병합 참고 |
main@{yesterday} | reflog 기준 어제 시점의 main | git diff main@{yesterday} |
git log --oneline main.. # 지금 브랜치에서 main 이후 만든 커밋 (= main..HEAD)
git log --branches --not --remotes # 모든 브랜치에서 아직 push 안 한 커밋
git cherry -v main # main에 아직 반영 안 된 커밋 (내용이 같으면 cherry-pick된 것으로 보고 - 표시)
git branch --contains <커밋> # 이 커밋을 포함한 브랜치
git tag --contains <커밋> # 이 커밋이 들어간 릴리스 태그
git log --oneline --left-right --cherry-pick HEAD...feature # 양쪽 차이에서 이미 cherry-pick된(내용이 같은) 커밋은 빼고
git describe --tags --abbrev=0 # 지금 커밋에서 가장 가까운 태그 (이 변경이 어느 릴리스 이후인가)log 필터
git log -n 5 # 마지막 5개
git log --author="kim" # 작성자 (정규식)
git log --since="2 weeks ago" --until="yesterday"
git log --grep="login" -i # 커밋 메시지 검색 (대소문자 무시)
git log --all --grep="hotfix" # 모든 브랜치에서
git log -p -- src/auth.ts # 이 파일을 바꾼 커밋과 diff
git log --follow -p -- src/auth.ts # 이름이 바뀐 이전 경로까지 따라가기
git log --no-merges # merge 커밋 빼기
git log --first-parent main # main에 직접 들어온 커밋·merge만 (PR 단위로 보기)
git log --stat --reverse main.. # 파일별 변경량, 오래된 것부터
git log --oneline --graph --all # 브랜치 그래프
git shortlog -sn # 작성자별 커밋 수--author나--grep을 여러 번 쓰면 OR로 묶인다.--grep조건을 모두 만족하는 커밋만 보려면--all-match를 붙인다.--first-parent는 merge 커밋으로 PR을 합치는 저장소에서 "언제 무엇이 들어왔나"를 PR 단위로 보여 준다.
지금 코드에서 찾기: git grep
git grep -n "TODO" # 줄 번호와 함께
git grep --heading --break -n "useAuth" # 파일별로 묶어서
git grep "TODO" v2.5 # 특정 태그·커밋 시점의 코드에서
git grep -e "foo" --and -e "bar" # 한 줄에 둘 다 있는 곳추적 중인 파일만 뒤지므로 node_modules나 빌드 결과물이 걸리지 않고, 과거 커밋을 체크아웃하지 않고도 그 시점 코드를 검색한다.
코드가 생기거나 사라진 커밋 찾기: pickaxe
| 옵션 | 찾는 커밋 | 쓰임 |
|---|---|---|
-S<문자열> | 그 문자열의 등장 횟수가 바뀐 커밋 | 함수·상수가 처음 추가되거나 지워진 커밋 |
-S<정규식> --pickaxe-regex | 위와 같되 정규식으로 | |
-G<정규식> | diff의 추가·삭제 줄에 패턴이 들어 있는 커밋 | 그 줄 근처를 고친 커밋까지 모두 |
git log -S"MAX_RETRY" --oneline # MAX_RETRY가 생기거나 없어진 커밋
git log -G"retry\(" -p # retry( 를 건드린 모든 커밋과 diff-S는 같은 줄 안에서 값만 바꾼 커밋(MAX_RETRY = 3 → 5)은 잡지 못한다. 등장 횟수가 그대로이기 때문이다. 이럴 때 -G를 쓴다.
함수나 줄 범위의 변천사: log -L
git log -L 40,60:src/auth.ts # 이 줄 범위가 바뀐 커밋과 그 부분 diff
git log -L :validateToken:src/auth.ts # 함수 이름으로줄마다 마지막 수정: blame
git blame src/auth.ts
git blame -L 40,60 src/auth.ts # 일부 줄만
git blame -w -C -C src/auth.ts # 공백 변경 무시, 다른 파일에서 옮겨 온 줄은 원래 커밋으로- blame은 마지막으로 바꾼 커밋만 알려 준다. 포매터 일괄 적용 같은 커밋이 있으면 모든 줄이 그 커밋으로 덮인다.
- 그런 커밋 해시를
.git-blame-ignore-revs파일에 적고git config blame.ignoreRevsFile .git-blame-ignore-revs로 설정하면 blame이 건너뛴다. GitHub의 blame 화면도 저장소 루트의 이 파일을 읽는다. - blame은 사람을 탓하는 도구가 아니라, 그 줄이 들어온 커밋과 PR의 맥락을 찾는 입구다. 해시를 찾았으면
git show <해시>로 메시지와 diff를 본다.
버그를 넣은 커밋 찾기: bisect
git bisect는 "잘 되던 커밋"과 "깨진 커밋" 사이를 이진 탐색한다. 커밋이 1,000개여도 10번 남짓만 확인하면 된다.
git bisect start
git bisect bad # 지금(HEAD)은 깨졌다
git bisect good v2.4.0 # 이 태그 때는 됐다
# Git이 중간 커밋을 체크아웃한다 → 확인하고 결과를 알린다
git bisect good # 또는 git bisect bad, 판단할 수 없으면 git bisect skip
# ... 반복하면 "<해시> is the first bad commit"
git bisect reset # 원래 브랜치로 돌아간다확인을 스크립트로 할 수 있으면 끝까지 자동으로 돌린다.
git bisect start HEAD v2.4.0
git bisect run npm test # 종료 코드 0 = good, 1~127(125 제외) = bad, 125 = skip- 커밋마다 빌드가 돼야 bisect가 정확하다. squash로 큰 커밋 하나가 되면 범위를 좁히지 못한다(merge·squash·rebase 언제 쓰나).
- 버그가 아니라 "성능이 바뀐 시점"처럼 good·bad가 어색하면
git bisect start --term-old=fast --term-new=slow로 이름을 바꾼다.
그 밖의 조회
| 하고 싶은 일 | 명령 |
|---|---|
| 다른 브랜치의 파일 내용 보기(체크아웃 없이) | git show main:src/config.ts |
| 어떤 커밋에서 바뀐 파일 목록 | git show --name-only <커밋> |
| 충돌 중인 파일 목록 | git diff --name-only --diff-filter=U |
| 브랜치의 커밋 수 | git rev-list --count main |
| 첫 커밋(루트) 찾기 | git rev-list --max-parents=0 HEAD |
| 커밋이 어느 태그·브랜치 이름으로 닿나 | git name-rev --name-only <커밋> |
정리
- 지금 코드면
git grep, 코드가 언제 생겼나면log -S/-G, 범위의 변천사면log -L, 줄의 마지막 수정이면blame, 버그 시작점이면bisect. - 범위 표기
A..B(B에만 있는 것)와A...B(한쪽에만 있는 것)를 구분하면 "어디에 무엇이 있나" 질문이 대부분 풀린다. - 포매팅 커밋은
.git-blame-ignore-revs로 blame에서 뺀다. - 이력 검색은 커밋이 작고 메시지가 좋을 때 가장 잘 된다. 커밋 습관은 커밋 컨벤션에 있다.
관련 노트: Git 기본 명령과 파일 상태, Git 되돌리기와 이력 다루기, merge·squash·rebase 언제 쓰나, 커밋 컨벤션과 자동 검사, 이분 탐색
원본 기록8
- GitHub 원문 (새 창) github.com/arslanbilal/git-cheat-sheet
- GitHub 원문 (새 창) github.com/mingrammer/git-tips
- 원문 (새 창) git-scm.com/docs/git-log
- 원문 (새 창) git-scm.com/docs/gitrevisions
- 원문 (새 창) git-scm.com/docs/git-grep
- 원문 (새 창) git-scm.com/docs/git-blame
- 원문 (새 창) git-scm.com/docs/git-bisect
- GitHub 원문 (새 창) github.com/k88hudson/git-flight-rules/blob/master/README_kr.md