가이드

git log, diff, show, blame: Git에서 프로젝트 히스토리 읽는 법

업데이트: · Skillaria.Top

git log는 커밋 목록을 보여 주고 작성자, 날짜, 파일, 텍스트로 걸러 낼 수 있습니다. git diff는 작업 폴더, 인덱스, 임의의 커밋 사이의 차이를 비교하고, git show는 커밋 하나를 통째로 보여 주며, git blame은 파일의 각 줄을 마지막으로 바꾼 커밋을 알려 줍니다.

네 가지 명령으로 프로젝트 히스토리에 대한 거의 모든 질문에 답할 수 있습니다. git log는 "무슨 일이 있었나"에, git diff는 "정확히 무엇이 바뀌었나"에, git show는 "이 커밋의 내용은 무엇인가"에, git blame은 "이 줄을 누가, 언제 썼나"에 답합니다. 아래에는 일상 개발에서 실제로 쓰는 옵션과 함께 각 명령의 실용적인 활용법을 정리했습니다.

git log: 커밋 목록 보기

옵션 없이 git log를 실행하면 현재 브랜치의 커밋이 최신순으로 나옵니다. 전체 SHA-1 해시, 작성자, 날짜, 메시지가 표시됩니다. 출력은 페이저(보통 less)에서 열립니다. 스페이스는 다음 페이지, /텍스트는 검색, q는 종료입니다.

commit 7be41d0c9a2e4f1b8d6c3e5a7f9b0c2d4e6f8a1b
Author: Anna Petrova <anna@example.com>
Date:   Mon Oct 5 14:22:10 2026 +0300

    feat: кэширование ответов API

해시를 전부 복사할 필요는 없습니다. Git은 고유하게 식별되는 4자 이상의 앞부분을 이해하며, 실무에서는 7자면 충분합니다.

간결한 출력: --oneline

git log --oneline -10
# 7be41d0 (HEAD -> main, origin/main) feat: кэширование ответов API
# 1c02e8f fix: таймаут запросов
# 9a4b3c2 refactor: вынес клиент в модуль

-10(또는 -n 10)은 커밋 수를 제한합니다. 괄호 안의 표시는 HEAD, 로컬 및 원격 브랜치, 태그가 어디에 있는지 보여 줍니다.

브랜치 그래프: git log --graph

"git graph"를 찾는 사람이 보통 원하는 것이 바로 이것입니다. 분기와 병합을 터미널에 그려 줍니다.

git log --oneline --graph --all
# * 3e1f0aa (feature/auth) feat: вход по токену
# | * 7be41d0 (HEAD -> main) feat: кэширование ответов API
# |/
# * 1c02e8f fix: таймаут запросов
# *   5d2c7b1 Merge branch 'feature/search'
# |\
# | * 8f3a9e0 feat: поиск
# |/
# * 9a4b3c2 refactor: вынес клиент в модуль

--all은 현재 브랜치만이 아니라 모든 브랜치를 보여 줍니다. 별칭을 만들어 두면 편합니다: git config --global alias.lg "log --oneline --graph --all --decorate". 이후 git lg만 입력하면 됩니다.

원하는 형식: --pretty=format

git log --pretty=format:"%h %ad %an %s" --date=short
# 7be41d0 2026-10-05 Anna Petrova feat: кэширование ответов API

주요 자리표시자: %h는 짧은 해시, %H는 전체 해시, %an은 작성자, %ae는 작성자 이메일, %ad는 작성 날짜, %ar는 상대 날짜("2 days ago"), %s는 메시지 제목입니다.

git log로 히스토리 필터링하기

작성자와 날짜로

git log --author="Anna"
git log --since="2 weeks ago" --until="2026-10-01"
git log --since=yesterday --oneline

--author는 정규 표현식을 받으며, 이름과 이메일 모두에서 찾습니다. Git은 날짜를 자유 형식과 ISO 형식 모두로 이해합니다.

메시지 텍스트로

git log --grep="fix" -i --oneline

-i는 대소문자를 구분하지 않습니다. 팀이 메시지에 이슈 번호를 적는다면, 이렇게 해서 특정 작업과 관련된 모든 커밋을 빠르게 찾을 수 있습니다.

파일이나 폴더로

git log --oneline -- src/api/client.py
git log --follow -p -- src/api/client.py

두 개의 하이픈(--)은 경로와 브랜치를 구분합니다. --follow는 이름 변경을 거치며 파일의 히스토리를 이어 줍니다(한 파일에 대해서만 동작합니다). -p는 각 커밋의 패치를 보여 줍니다.

바뀐 코드로 검색: 해당 코드가 바뀐 커밋 찾기

git log -S "retry_count" --oneline     # 문자열의 등장 횟수가 바뀐 커밋
git log -G "timeout\s*=" --oneline    # diff의 줄이 정규 표현식과 맞는 커밋

-S는 함수나 변수가 추가되거나 삭제된 커밋을 찾습니다. 어느 시점에 코드 조각이 사라졌는지 알아볼 때 대체할 수 없는 도구입니다.

커밋 범위

git log main..feature      # feature에 있지만 main에는 없는 것
git log origin/main..HEAD  # 내 로컬 커밋 중 아직 보내지 않은 것
git log --no-merges        # 병합 커밋 제외
git log --stat             # 바뀐 파일과 줄 수 표시

git diff: 무엇이 바뀌었나

git diff를 이해하는 핵심은 어떤 두 상태를 비교하는지 아는 것입니다. "모든 걸 바꿨는데 diff가 비어 있다"는 질문은 대부분 여기서 나옵니다.

명령비교 대상
git diff작업 폴더와 인덱스 비교(준비되지 않은 변경)
git diff --staged(--cached)인덱스와 마지막 커밋 비교(커밋에 들어갈 내용)
git diff HEAD작업 폴더와 마지막 커밋 비교(전부 합친 것)
git diff A B두 커밋, 브랜치 또는 태그 비교
git diff A...BA에서 갈라진 뒤 B에서 바뀐 내용

git add를 했다면 일반 git diff는 비어 보입니다. 변경이 이미 인덱스에 있기 때문이므로 --staged를 보세요. 한 번도 추가하지 않은 새 파일은 diff에 전혀 나타나지 않습니다.

diff 출력 읽는 법

diff --git a/config.py b/config.py
index 3b18e51..a1c4f02 100644
--- a/config.py
+++ b/config.py
@@ -10,7 +10,7 @@ DEFAULTS = {
     "host": "localhost",
-    "timeout": 5,
+    "timeout": 30,
     "retries": 3,

-로 시작하는 줄은 삭제, +로 시작하는 줄은 추가, 나머지는 주변 문맥입니다. @@ -10,7 +10,7 @@ 표시는 이 조각이 이전과 이후 버전 모두에서 10번째 줄부터 7줄을 차지한다는 뜻입니다.

유용한 git diff 옵션

git diff --stat main feature      # 파일별 요약
git diff --name-only HEAD~3       # 바뀐 파일 이름만
git diff --word-diff               # 단어 단위 변경, 텍스트에 편리
git diff -w                        # 공백 변경 무시
git diff main feature -- src/      # 특정 폴더로 제한

커밋하기 전에는 git diff --staged를 확인하세요. 디버그용 print나 잘못 추가한 파일을 잡아낼 마지막 기회입니다.

git show: 커밋 하나를 통째로 보기

git show는 커밋의 메타데이터와 부모 대비 diff를 보여 줍니다. 인수가 없으면 마지막 커밋입니다.

git show 7be41d0
git show HEAD~2 --stat           # 패치 없이 요약만
git show v1.2.0                  # 태그: 주석과 커밋
git show main:src/config.py      # 커밋 시점의 파일 내용

마지막 형식 <리비전>:<경로>는 특히 유용합니다. 체크아웃하지 않고도 옛 버전의 파일을 볼 수 있습니다. 출력을 파일로 리다이렉트하면 checkout 없이 지워진 내용을 복구할 수도 있습니다.

git blame: 이 줄을 누가 바꿨나

git blame 파일은 각 줄마다 마지막으로 그 줄을 바꾼 커밋, 작성자, 날짜를 보여 줍니다. 이름은 비난하는 듯하지만, 실제로는 문맥을 찾는 도구입니다. 커밋을 찾아 메시지를 읽고 왜 그렇게 했는지 이해하는 데 쓰입니다.

git blame -L 40,60 src/api/client.py
# 1c02e8f3 (Anna Petrova 2026-09-28 11:04:51 +0300 41)     timeout = settings.timeout
# 9a4b3c2e (Ivan Smirnov 2026-09-14 18:30:02 +0300 42)     session = build_session()
  • -L 40,60 — 줄 범위만 보기. -L :함수이름도 가능합니다.
  • -w — 공백 변경을 무시해서, 서식 정리 커밋에 잘못 걸리지 않게 합니다.
  • -C — 다른 파일에서 옮겨 온 줄도 추적합니다.
  • --ignore-rev <해시> 또는 .git-blame-ignore-revs 파일 — 자동 포맷팅 같은 대량 변경 커밋을 건너뜁니다.

전형적인 추적 순서: git blame이 커밋을 찾고, git show가 그 커밋을 통째로 보여 주고, 파일의 git log가 주변 변경을 보여 줍니다.

과거로 이동하기: HEAD~ 와 HEAD^

커밋은 해시만이 아니라 상대 위치로도 가리킬 수 있습니다. HEAD~1은 현재 커밋의 부모, HEAD~3은 조부모의 부모입니다. HEAD^2는 병합 커밋의 두 번째 부모입니다. 브랜치, 태그, 원격 브랜치 이름도 쓸 수 있습니다: origin/main~2. 옛 커밋의 프로젝트 전체를 보려면 git switch --detach <해시>를, 돌아오려면 git switch -를 쓰세요.

좋은 히스토리와 나쁜 히스토리

이 명령들은 히스토리가 의미 있을 때만 쓸모가 있습니다. "fix", "wip", "수정 더" 같은 메시지는 git log --grep과 git blame을 쓸모없게 만듭니다. 좋은 커밋은 하나의 논리적 변경이며, 무엇을 왜 했는지 설명하는 제목을 가집니다. 예: fix: 느린 게이트웨이 때문에 API 타임아웃을 30초로 증가. 반년 뒤 blame이 이런 커밋을 찾아 주면 한 시간을 아낄 수 있습니다.

실습: 히스토리로 버그 추적하기

이번 릴리스 후 API 요청이 타임아웃으로 실패하기 시작했다고 해 봅시다. 명령을 연결하면 몇 분 안에 원인에 닿을 수 있습니다.

  1. 릴리스에 무엇이 들어갔는지 봅니다: git log v1.4.0..v1.5.0 --oneline. 목록은 짧지만 제목만으로는 범인이 분명하지 않습니다.
  2. 파일로 좁힙니다: git log v1.4.0..v1.5.0 --oneline -- src/api/. 두 개의 커밋이 남습니다.
  3. 코드로 검색합니다: git log -S "timeout" --oneline -- src/api/가 타임아웃 값이 바뀐 커밋을 찾습니다.
  4. 그 커밋을 통째로 봅니다: git show 1c02e8f. diff에서 타임아웃이 30초에서 5초로 줄었고, 메시지에는 "UI 응답 속도 개선"이라고 적혀 있습니다.
  5. 이 줄을 누가 또 건드렸는지 봅니다: git blame -L :build_session src/api/client.py.

이후는 엔지니어링 작업입니다. 값을 되돌리거나, 설정으로 빼내거나, git revert로 커밋을 되돌립니다. 커밋이 수백 개라서 눈으로 범인을 찾을 수 없다면 git bisect가 도움이 됩니다. 이진 탐색으로 몇 단계 만에 동작을 깨뜨린 커밋을 찾아 줍니다.

편리한 설정

git config --global log.date iso            # log의 날짜 형식
git config --global diff.colorMoved zebra   # diff에서 옮겨진 줄 강조
git config --global core.pager "less -FRX"  # 짧은 출력은 페이저 없이

출력을 스크립트로 처리한다면 색상과 페이저를 끄세요: git --no-pager log --format="%H %s" --no-color. 기계가 읽을 때는 전체 해시 %H를 쓰세요. 큰 저장소에서는 짧은 접두사가 시간이 지나며 모호해질 수 있습니다.

정리

--oneline, --graph, --author, -S, 경로 같은 필터를 쓴 git log는 "무슨 일이 있었나"에 답합니다. git diff는 작업 폴더, 인덱스, 커밋을 비교하며, 기본 비교 대상이 무엇인지 기억하는 것이 핵심입니다. git show는 커밋 하나나 옛 파일 버전을 펼쳐 보여 주고, git blame은 코드의 한 줄에서 그 줄을 만든 결정까지 거슬러 올라갑니다. 히스토리 읽기와 커밋 탐색은 Git 강의에서 실습으로 다룹니다.

자주 묻는 질문

git log에서 어떻게 빠져나오나요?

q를 누르면 됩니다. 출력은 less 페이저에서 열립니다. 페이저 없이 출력하려면 git --no-pager log를 쓰거나 -n으로 개수를 적게 지정하세요.

삭제된 파일의 히스토리는 어떻게 보나요?

git log --oneline -- 경로/파일을 두 개의 하이픈과 함께 실행하세요. 삭제 전의 내용은 git show <해시>^:경로/파일로 볼 수 있습니다.

로컬 브랜치를 원격 브랜치와 비교하려면 어떻게 하나요?

먼저 git fetch를 하고, git diff origin/main 또는 git log origin/main..HEAD로 아직 보내지 않은 커밋을 보세요.

그래픽으로 히스토리를 볼 수 있는 도구가 있나요?

네, Git에 gitk가 포함되어 있고, VS Code, JetBrains IDE, GitHub와 GitLab 웹 인터페이스에도 히스토리 그래프가 있습니다.

git diff가 아무것도 보여 주지 않는 이유는 무엇인가요?

대개 git add로 변경을 인덱스에 올렸기 때문입니다. git diff --staged를 보세요. 추적되지 않는 새 파일은 git diff에 나타나지 않습니다.

영상으로 이 주제 배우기

이 주제는 “Git 완전 정복: 초보에서 능숙한 개발자로” 강의에서 실습과 함께 자세히 다룹니다.

강의로 이동