동작하는 코드
예제 1: git log 고급 검색
히스토리가 있는 저장소를 준비합니다:
git init
echo "v1" > app.py && git add app.py && git commit -m "feat: 초기 앱"
echo "login" >> app.py && git add app.py && git commit -m "feat: 로그인 기능 추가"
echo "bug fix" >> app.py && git add app.py && git commit -m "fix: 로그인 버그 수정"
echo "profile" >> app.py && git add app.py && git commit -m "feat: 프로필 페이지 추가"
echo "style" >> app.py && git add app.py && git commit -m "style: 코드 포맷 정리"
커밋 메시지로 검색:
git log --grep="feat" --oneline
출력:
e4f5g6h feat: 프로필 페이지 추가
b2c3d4e feat: 로그인 기능 추가
a1b2c3d feat: 초기 앱
특정 내용 변경을 포함한 커밋 찾기:
# "login"이 추가되거나 삭제된 커밋
git log -S "login" --oneline
출력:
c3d4e5f fix: 로그인 버그 수정
b2c3d4e feat: 로그인 기능 추가
예제 2: 작성자로 검색
git log --author="홍길동" --oneline
# 날짜 범위
git log --after="2024-01-01" --before="2024-02-01" --oneline
# 특정 파일의 변경 히스토리
git log --oneline app.py
예제 3: git blame
어느 줄이 누가 언제 작성했는지:
git blame app.py
출력:
a1b2c3d (홍길동 2024-01-15 10:30:01 +0900 1) v1
b2c3d4e (홍길동 2024-01-15 10:31:00 +0900 2) login
c3d4e5f (김철수 2024-01-16 09:00:00 +0900 3) bug fix
e4f5g6h (홍길동 2024-01-17 14:00:00 +0900 4) profile
각 줄마다:
- 커밋 해시 (앞 8자리)
- 작성자
- 날짜/시간
- 줄 번호
- 내용
직접 수정하기
git log -S: 특정 코드 변경 추적
"이 코드가 언제 추가됐지?"를 찾을 때:
# "getUserById"가 추가되거나 삭제된 커밋
git log -S "getUserById" --oneline
# 변경 내용까지 보기
git log -S "getUserById" -p
# 정규식으로 검색
git log -G "user.*[Bb]y[Ii]d" --oneline
git blame 활용
# 특정 줄 범위만 (10~20줄)
git blame -L 10,20 app.py
# 더 짧은 해시로
git blame --abbrev=7 app.py
# 공백 변경 무시
git blame -w app.py
blame 결과로 히스토리 탐색:
git blame app.py
# c3d4e5f (김철수 ...) 3) bug fix
# 해당 커밋 상세 보기
git show c3d4e5f
# 해당 커밋 전의 blame 보기
git blame c3d4e5f~1 app.py
git cherry-pick: 특정 커밋만 가져오기
다른 브랜치의 특정 커밋만 현재 브랜치에 적용:
git checkout -b feature-a
echo "기능 A" >> app.py && git add app.py && git commit -m "feat: 기능 A 추가"
echo "버그 수정 A" >> app.py && git add app.py && git commit -m "fix: 기능 A 버그 수정"
git checkout main
git log --oneline --all
출력:
f1g2h3i (feature-a) fix: 기능 A 버그 수정
e0f1g2h (feature-a) feat: 기능 A 추가
a1b2c3d (HEAD -> main) style: 코드 포맷 정리
...
버그 수정만 main에 가져오기:
git cherry-pick f1g2h3i # fix 커밋만 선택
git log --oneline
출력:
j0k1l2m (HEAD -> main) fix: 기능 A 버그 수정 ← 새 해시로 복사됨
a1b2c3d style: 코드 포맷 정리
cherry-pick은 커밋을 복사합니다. 원본 커밋은 그대로 있고 새 해시로 현재 브랜치에 추가됩니다.
여러 커밋 cherry-pick:
# 커밋 2개 선택
git cherry-pick a1b2c3d e4f5g6h
# 범위로 선택 (a부터 b까지, a 제외)
git cherry-pick a1b2c3d..e4f5g6h
# 범위로 선택 (a 포함)
git cherry-pick a1b2c3d^..e4f5g6h
git bisect: 버그 도입 커밋 찾기
"언젠가부터 이 기능이 안 되는데 어떤 커밋에서 깨졌지?"
# bisect 시작
git bisect start
git bisect bad HEAD # 현재: 버그 있음
git bisect good a1b2c3d # 이 커밋은 정상이었음
# Git이 중간 커밋을 자동 체크아웃
# 테스트 후 결과 보고
git bisect good # 이 커밋은 정상
# 또는
git bisect bad # 이 커밋에 버그 있음
# 몇 번 반복하면 Git이 범인 커밋을 찾아줌
# 완료 후 원래 상태로
git bisect reset
"왜?" — 히스토리 탐색이 필요한 상황
| 상황 | 도구 |
| -------------------------------- | ------------------- |
| "언제 이 기능이 추가됐지?" | git log -S "코드" |
| "이 줄 누가 작성했지?" | git blame |
| "언제부터 버그가 생겼지?" | git bisect |
| "저 브랜치의 특정 커밋만 필요해" | git cherry-pick |
| "특정 작업자의 커밋만 보고 싶어" | git log --author |
실전 디버깅 시나리오
# 1. 버그 발견: 특정 함수가 잘못 동작
# 2. blame으로 마지막 수정자 확인
git blame -L 45,60 src/auth.js
# 3. 해당 커밋 확인
git show c3d4e5f
# 4. 그 커밋 전후 비교
git diff c3d4e5f~1 c3d4e5f
# 5. 언제부터인지 bisect로 범위 좁히기
git bisect start
git bisect bad HEAD
git bisect good v1.0.0
흔한 실수
실수 1: cherry-pick 충돌 처리 방법 모름
git cherry-pick f1g2h3i # 충돌 발생
# CONFLICT: ...
# 충돌 해결 후
git add 파일명
git cherry-pick --continue
# 또는 취소
git cherry-pick --abort
실수 2: git log -S와 --grep 혼동
# --grep: 커밋 메시지 검색
git log --grep="로그인" # 메시지에 "로그인"이 있는 커밋
# -S: 코드 변경 내용 검색
git log -S "login" # 코드에 "login"이 추가/삭제된 커밋
실수 3: blame으로 사람 탓하기
git blame의 목적은 코드 문맥을 이해하는 것이지, 잘못한 사람을 찾는 게 아닙니다. 그 사람이 왜 그렇게 작성했는지 커밋 메시지와 PR을 찾아보세요.
심화 학습
git log --format 커스터마이징
# 커밋 해시, 작성자, 날짜, 메시지
git log --format="%h %an %ar %s"
# 예쁜 색상 출력
git log --format="%C(yellow)%h%C(reset) %C(blue)%an%C(reset) %s"
# alias로 등록
git config --global alias.lg "log --format='%C(yellow)%h%C(reset) %C(blue)%an%C(reset) %ar %s' --graph --all"
git lg
git shortlog: 기여자 요약
# 기여자별 커밋 수 요약
git shortlog -sn
# 특정 기간
git shortlog -sn --after="2024-01-01"
출력:
45 홍길동
23 김철수
12 이영희
오픈소스 프로젝트 기여자 목록이나 팀 활동 현황 파악에 유용합니다.
git stash vs cherry-pick vs patch
브랜치 간 코드를 이동하는 방법:
# cherry-pick: 특정 커밋 복사
git cherry-pick 커밋해시
# patch: 파일로 변경 사항 추출 후 적용
git format-patch -1 커밋해시
git am 0001-커밋메시지.patch
# 임시로 파일만 복사
git show 커밋해시:경로/파일.txt > 복사본.txt
- 여러 커밋을 만들고
git log --grep="feat" --oneline으로 feat 커밋만 검색하세요. git log -S "특정코드" --oneline으로 특정 코드가 변경된 커밋을 찾아보세요.git blame 파일명으로 각 줄의 작성자와 커밋을 확인하세요.- feature 브랜치를 만들고 커밋 2개를 추가한 후,
git cherry-pick 커밋해시로 main에 하나만 가져오세요. git bisect를 시뮬레이션해보세요 (여러 커밋 후 good/bad를 번갈아 지정하며 범인 커밋 찾기).
Q1. git log -S "getUserById"와 git log --grep="getUserById"의 차이는?
- A)
-S는 작성자 검색,--grep은 내용 검색 - B)
-S는 코드에서 해당 텍스트가 추가/삭제된 커밋 검색,--grep은 커밋 메시지 검색 - C)
-S는 빠른 검색,--grep은 정확한 검색 - D) 두 명령어는 동일한 결과를 보여줌