메인 콘텐츠로 건너뛰기
index.js를 열어보니 console.log("hello world");가 있어요. 처음에는 "hello"였는데 어느 커밋에서 바뀌었을까요? 중간에 다른 문자열도 있었을까요? 작업 트리·스테이징 영역·커밋 실습에서는 같은 줄을 두 번 바꿔 기록했어요. 이번에는 이미 남긴 기록을 찾아 실제로 바뀐 줄과 당시 파일을 확인해봐요.

목록에서 찾고, 한 커밋을 읽고, 두 시점을 비교해요

커밋은 파일의 스냅샷과 메시지, 작성자, 부모 커밋 등의 정보를 연결해요. Git은 스냅샷을 비교해서 차이를 보여줘요. 이 글은 병합 없이 일렬로 이어진 세 커밋을 기준으로 해요.

시작 상태를 맞춰요

명령은 Bash 기준이에요. 코드 실행이나 Node.js 설치는 필요하지 않아요. 앞편을 끝낸 연습 저장소에서 이어가요. 준비를 마친 뒤에는 조회 명령만 실행하므로 브랜치, 작업 파일, 인덱스, 커밋 이력은 바뀌지 않아요. 다른 작업이 섞여 있다면 되돌리지 말고 새 연습 저장소를 준비해요.
Git 설치는 첫 커밋 실습을 참고해요. git init -b main에는 Git 2.28 이상이 필요해요. 별도 hook이나 커밋 서명 설정이 없는 연습 환경을 기준으로 해요.기존 Git 저장소 밖의 폴더에서 실행해요. 같은 이름의 폴더가 있어 mkdir가 실패하면 멈추고 새 이름을 골라요.
아래 >는 파일을 덮어써요. 방금 만든 빈 연습 폴더에서만 실행해요. 작성자 설정은 이 저장소에만 적용하며, 원격 저장소는 연결하지 않아요.
앞편에서 관찰한 스테이징 중간 상태를 반복하지 않고, 이번 조회에 필요한 세 스냅샷과 메시지를 준비한 거예요. 작성 시각 등이 다르므로 앞편과 커밋 ID까지 같을 필요는 없어요.
같은 터미널에서 연습 저장소의 상태를 확인해요.
status에는 main과 working tree clean이 보여야 해요. log에는 표에 적힌 세 커밋이 있어야 해요. 파일 내용은 차례로 console.log("hello world");, # Git practice이고, 원격 출력은 없어야 해요. 다르면 준비 상태부터 맞춰요. 출력이 별도 보기 화면으로 열리면 q로 나올 수 있어요. 아래 명령은 모두 저장소 루트에서 실행해요.

log로 후보를 찾고 show로 확인해요

1

기록 목록에서 코드 변경 찾기

먼저 최근 기록을 짧게 보고, index.js와 관련된 기록으로 범위를 좁혀요.
첫 명령에서는 위에서부터 Change greeting to hello world, Change greeting to hello git, Add initial script and README가 보여요. 각 메시지 앞에는 실제 커밋의 축약 해시가 붙어요. -3은 최대 세 커밋만 보여달라는 뜻이에요.-- index.js는 파일 경로로 이력을 좁혀요. 이 예제에서는 세 커밋 모두 index.js를 변경했으므로 목록이 같아요. --는 옵션·커밋 이름과 파일 경로를 구분해요.--grep='hello git'은 커밋 메시지를 검색해요. 파일 안의 hello git을 찾는 명령은 아니에요. 여기서는 Change greeting to hello git 하나가 나와요. 목록과 검색 옵션은 git log 공식 문서를 참고해요.
2

찾은 커밋의 메시지와 변경 읽기

이번 이력에서 HEAD는 마지막 hello world 커밋을 가리켜요. HEAD~1은 그 부모인 hello git 커밋, HEAD~2는 부모를 두 번 따라간 초기 커밋이에요.
출력에서 커밋 ID, 작성자, 시각, 메시지와 코드 변경을 읽어봐요. 이 예제의 일반 커밋은 부모 커밋과 비교한 차이를 보여줘요. 변경 부분은 다음과 같아요. 파일명·해시를 나타내는 앞부분은 생략했어요.
앞의 -, +는 파일에 저장된 문자가 아니에요. 더 긴 파일에서는 공백으로 시작하는, 바뀌지 않은 문맥 줄도 나올 수 있어요. show와 패치 형식은 git show 공식 문서에 설명되어 있어요.HEAD~1 대신 방금 log에서 얻은 커밋 해시를 사용해도 돼요. HEAD~1은 현재 위치가 바뀌면 다른 커밋을 뜻할 수 있으므로, 특정 기록을 전달할 때는 해시를 남겨요. ~는 첫 번째 부모를 따라가는 표기이며 날짜순으로 몇 번째 기록이라는 뜻은 아니에요. 커밋을 지정하는 공식 규칙을 참고해요.
3

그때 파일 전체와 기록 시각 확인하기

바뀐 줄을 보면 문자열이 어떻게 달라졌는지 알 수 있어요. 당시 파일 전체가 필요하면 커밋 이름 뒤에 :파일경로를 붙여요.
첫 출력은 console.log("hello git");, 두 번째는 console.log("hello world");이에요. 과거 파일을 읽었을 뿐, 현재 작업 파일이 과거 내용으로 바뀌지는 않았어요.마지막 명령은 패치를 생략하고 커밋 정보를 자세히 보여줘요. AuthorDate는 작성 시각, CommitDate는 커밋을 기록한 시각이에요. 이 실습에서는 대개 같지만, 변경을 다른 이력에 옮기는 등의 작업에서는 달라질 수 있어요. 커밋 시각을 서비스 배포 시각으로 읽지는 않아요.

두 커밋의 diff에는 중간 과정이 나올까요?

이번에는 처음 코드와 마지막 코드를 비교해봐요. 실행 전에 중간 문자열인 "hello git"도 출력에 나올지 예상해보세요.
변경 줄만 발췌하면 아래와 같아요.
두 커밋의 diff는 양 끝의 스냅샷을 비교해요. 중간에 "hello git"이 있었던 과정은 이 결과에 나오지 않아요. 그 과정을 보려면 앞에서처럼 커밋별로 show를 읽거나, log -p로 각 커밋의 패치를 함께 봐요.
첫 명령에서는 최근 것부터 "hello git" → "hello world", "hello" → "hello git" 변경을 읽을 수 있어요. 두 번째는 비교 순서를 뒤집었으므로 -console.log("hello world");, +console.log("hello");이 나와요. 명령이 코드를 되돌린 것은 아니에요. 마지막 명령은 두 시점의 README 내용이 같아서 출력이 없어요. git diff 공식 문서의 두 커밋 비교가 이 동작의 기준이에요. git diff HEAD~2..HEAD도 이 경우 같은 두 끝을 비교해요. 반면 git log HEAD~2..HEAD는 HEAD~2에서 도달할 수 있는 커밋을 제외한 이력을 골라요. 이번 직선 이력에서는 코드 변경 두 커밋만 나와요. 같은 .. 표기를 보고 두 명령을 같은 의미로 읽지 않아요.

diff가 비어 있어도 질문은 다를 수 있어요

앞편에서 본 미커밋 변경 비교와 이번 이력 비교를 나란히 놓아봐요. 앞의 두 결과가 비어 있어도 과거 코드 변경이 없었던 것은 아니에요. 현재 남은 변경이 있는지와 두 과거 기록이 다른지는 서로 다른 질문이에요. 또 두 끝의 파일이 같더라도, 중간에 고쳤다가 원래 내용으로 돌아온 기록은 있을 수 있어요.

코드를 왜 바꿨는지도 알 수 있을까요?

지금까지 확인한 사실은 “문자열을 hello git으로 바꾼 뒤 hello world로 바꿨다”예요. 메시지와 패치가 같은 변경을 가리키는지도 확인했어요. 하지만 Change greeting to hello git에는 문자열을 바꾼 이유가 적혀 있지 않아요. 요구사항이 달라졌는지, 오타를 고친 것인지 Git이 알아서 기록하지는 않아요. 앞편에서 두 번 커밋한 이유는 세 상태를 관찰하기 위해서였어요. 실무에서는 패치로 무엇이 바뀌었는지 확인하고, 커밋 메시지 본문이나 연결된 이슈·리뷰에서 의도를 찾아요. 근거가 없다면 이유를 추측해서 확정하지 않아요. 앞으로 기록을 남길 때 변경 이유와 선택의 제약을 함께 적으면 다음 사람이 같은 질문을 덜 하게 돼요.

예상과 다른 결과가 나왔다면

기록을 읽은 뒤 상태를 확인해요

  • main에는 처음과 같은 세 커밋이 있고 working tree clean이에요. 두 미커밋 diff는 비어 있어요.
  • show HEAD~1에서 "hello" → "hello git" 변경을 찾았어요.
  • show HEAD~1:index.js는 과거 파일을 읽었고, 현재 파일은 여전히 console.log("hello world");예요.
  • 초기·마지막 커밋의 diff에는 "hello" → "hello world"만 나와요. 중간 과정은 커밋별 패치에서 확인했어요.
  • README는 # Git practice이고 원격 저장소는 없어요.
어떤 기록인지 찾을 때는 log, 고른 기록의 메시지와 변경을 읽을 때는 show, 두 시점의 차이를 볼 때는 diff를 사용해요. 다음에 변경의 근거를 전달할 때는 커밋 해시와 확인한 파일·패치를 함께 남겨보세요. 해시 조회 옵션은 현재 커밋 해시 확인하기에서 찾아볼 수 있어요. 기록을 읽었다면 이제 어떤 파일을 기록에서 제외할지도 살펴봐요. .gitignore와 파일 추적 실습에서 임시 로그와 이미 기록한 메모를 비교해요.